sqlserver 大欄位儲存格式(一)
資料頁
資料頁是包含已經被新增到某個資料庫表中的使用者資料的結構,SQLServer有3種資料頁面,每個頁面都以一種不同的格式儲存資料。分別是用於行內資料、行溢位資料和LOB資料的頁面。
和其他型別的頁面一樣,資料頁面具有8KB的固定長度,它們主要由3個主要部分組成,頁首、資料行和行偏移陣列
- 頁首
每個資料頁前96個位元組是頁首。
- 行內資料的資料行
頁首下面是表的真實資料行的儲存區域。單個數據行的最大容量是8060位元組的行內資料。行也可能有行溢位和儲存在獨立頁上的lob資料。
- 行偏移陣列
行偏移陣列是一塊2位元組的條目,其中每個目錄都是表示相應資料行起始頁的偏移量。每一行在這個陣列中都有一個2位元組條目。
行溢位資料:
超出8060位元組大小限制的一種儲存方式是使用變長列,因為對於變長資料來說,SQLServer可以在特殊的行溢位頁中儲存這些列,只要所有長度固定的列適合標準行內大小的限制。可以存在overflow頁上的資料型別包括varbinary、varchar、nvarchar和sqlvariant列。
- 建立最大定義長度大於8060位元組的一張表:
create table dbo.bigrows
(a varchar(3000),
b varchar(3000),
c varchar(3000),
d varchar(3000)
);
- 然後插入一條資料:
insert into bigrows selectreplicate('e',2100),
replicate('f',2100),replicate('g',2100),
replicate('h',2100);
- 用下列語句檢視頁面分佈情況:
select object_name(object_id) as name,
partition_id, partition_number aspnum, rows,
allocation_unit_id as au_id, type_descas page_type_desc,
total_pages as pages
from sys.partitions p joinsys.allocation_units a
on p.partition_id = a.container_id
whereobject_id=OBJECT_ID('dbo.bigrows')
結果:有兩頁用於儲存標準行內資料的一行,兩頁用於儲存行溢位資料的一行
- 然後用DBCC IND檢視頁面情況:
dbcc ind (Simple, bigrows, -1)
pagetype:
--1資料頁
--2索引頁
--3 LOB或行溢位頁, text_mixed
--4 LOB或行溢位,text_data
--8 GAM page
--9 sgam page
--10 IAM頁面
--11 pfs page
- 然後用DBCCPAGE檢視2189頁上面的資料,使用dbccPAGE前必須先執行:
DBCC TRACEON (3604);
dbcc page ('Simple',1,2189,3)
前面的一些內容就不看了,看一下這一頁上面儲存的資料內容(中間...省略了重複內容)
0000000000000000: 3000040004000004 0045085d 889110c5 18656565 0........E.].....eee
0000000000000014: 6565656565656565 65656565 65656565 65656565 eeeeeeeeeeeeeeeeeeee
... ...
0000000000000820: 6565656565656565 65656565 65656565 65656565 eeeeeeeeeeeeeeeeeeee
0000000000000834: 6565656565656565 65656565 65656565 65020000 eeeeeeeeeeeeeeeee...
0000000000000848: 0001000000471500 00340800 009f0800 00010000 .....G...4..........
000000000000085C: 0067676767676767 67676767 67676767 67676767 .ggggggggggggggggggg
0000000000000870: 6767676767676767 67676767 67676767 67676767 gggggggggggggggggggg
... ...
0000000000001068: 67676767 6767676767676767 67676767 67676767 gggggggggggggggggggg
000000000000107C: 6767676767676767 67676767 67676767 67676767 gggggggggggggggggggg
0000000000001090: 67686868 68686868 68686868 68686868 68686868 ghhhhhhhhhhhhhhhhhhh
... ...
0000000000001874: 6868686868686868 68686868 68686868 68686868 hhhhhhhhhhhhhhhhhhhh
0000000000001888: 6868686868686868 68686868 68686868 68686868 hhhhhhhhhhhhhhhhhhhh
000000000000189C: 6868686868686868 68686868 68686868 68686868 hhhhhhhhhhhhhhhhhhhh
00000000000018B0: 6868686868686868 68686868 68686868 68686868 hhhhhhhhhhhhhhhhhhhh
00000000000018C4: 68 h
這一頁上面儲存了我們前面插入的一行資料,可以看到a,c,d列都在這裡面直接儲存的,而b列卻找不到;b列就是我們這邊要找的overflow列,上面結果中紅色部分是24個位元組的overflow指標,結構如下:
- 下面是fn_dblog顯示的這個事務的結果,其中第5條的[RowLog Contents 0]記錄了上面一頁的資訊:
0x30000400040000040045085D889110C51865…6565020000000100000047150000340800009F0800000100000067676767…7676868686868…68
可以看到中間也是包含24位元組指標