6,129
社区成员
发帖
与我相关
我的任务
分享
LOB数据类型
当表中存在LOB类型数据(TEXT/NTEXT/IMAGE)时候:
默认的情况下(TEXT IN ROWS选项是关闭的)数据是不会存储在DATA页面上的.它是存储在属于自己的LOB页面上的,在数据页面只留下字节的指针;
在设置表选项来改变这个存储机制时候,他有可能会存储在DATA页面上。
那么我们来通过例子具体看下LOB类型数据的存储
/*----------------------------------------------------------------------
*auther:Poofly
*date:2010.3.14
*VERSION:
Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86)
Jul 9 2008 14:43:34
Copyright (c) 1988-2008 Microsoft Corporation
Enterprise Evaluation Edition on Windows NT 6.1 <X86> (Build 7600: )
*转载请注明出处
*更多精彩内容,请进http://blog.csdn.net/feixianxxx
------------------------------------------------------------------------*/
--建表(表源技术内幕)
if OBJECT_ID('Hastext') is not null
drop table Hastext
GO
create table Hastext
(
COL1 CHAR(3) NOT NULL,
COL2 VARCHAR(5) NOT NULL,
COL3 TEXT NOT NULL,--此处TEXT字段
COL4 VARCHAR(20) NOT NULL
)
--插入测试数据
INSERT Hastext
SELECT 'AAA','BBB',REPLICATE('X',250),'CCC'
--检查页面分布和类型
SELECT convert(char(7), object_name(object_id)) AS name,
partition_id, partition_number AS pnum, rows,
allocation_unit_id AS au_id, convert(char(17),type_desc) as page_type_desc,
total_pages AS pages
FROM sys.partitions p JOIN sys.allocation_units a
ON p.partition_id = a.container_id
WHERE object_id=object_id('dbo.Hastext');
--有IN_ROW_PAGE lOB_DATA 分配单元各有页,其中一页为IAM页。
--查找页面具体文件号和页面号
dbcc ind(tempdb,Hastext ,-1)
/*
PageFID PagePID iam_chain_type PageType
1 127 In-row data 10
1 126 In-row data 1 ---data page
1 174 LOB data 10
1 173 LOB data 3 ----LOB page
*/
--查看页面信息
dbcc traceon(3604) --此追踪可以显示页面输出结果
dbcc page(tempdb,1,126,1) --查看数据页的页面信息
/*
Slot 0, Offset 0x60, Length 40, DumpStyle BYTE
Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP VARIABLE_COLUMNS
Record Size = 40
Memory Dump @0x63D8C060
00000000: 30000700 41414104 00800300 15002580 ?...AAA.......%.
00000010: 28004242 420000e5 07000000 00ad0000 ?.BBB...........
00000020: 00010001 00434343 ?8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??....CCC PS:这里右边部分每一个小点表示一个字节
*/
--分析几个值:
我在这里分析下这个含有LOB数据类型的行的page读取方法 你可以对照我在上一偏文章<关于一般页面存储的研究>http://blog.csdn.net/feixianxxx/archive/2010/03/17/5390317.aspx的行结构进行对照 依次分解读取
30=>00110000 从左往右看第一个表示有变长列 第二个表示存在NULL位图
00=>00000000 未启用
0700=>0000000000001011 页位移量为 1+1+2+3(col1 char(3)),说明真正数据从第字节开始
414141=>010000010100000101000001 转成十进制 再转成ASICC码 值为A 即COL1 ‘AAA’
0400=>0000000000000100 一共列
08=>10000000 表里有列 最后位为 表示都不为NULL
0300=>0000000000000011 变长列为列 这里的TEXT列也算成变成列
1500=>0000000000010101 第一列变长列的终止位置
2580->1000000000100101 第二列变长列(TEXT)的终止位置
2800->0000000000101000=40 该列外为最后的可变列终止位置 正好就等于LENGTH 40
424242=>010000100100001001000010 转成十进制 再转成ASICC码 值为B 即COL1 ‘BBB’
0000e5 07000000 00ad0000 00010001 00==>这里的个字节是文本(TEXT)在这个DATA页面的指针
其中值ad00 0000是从这个指针留下来指向页面号的字节> Oxad00 0000
(Oxad00==>0000000010011101 转成十进制为 恰好是我们的LOB页面的页面号),
后面的->00000000 00000001=1是LOB页面所在的文件号
再后面的->00000000 00000001=1是该条记录在LOB页面的Slot号.
434343==>转成十进制 再转成ASICC码 值为C 即COL1 ‘CCC’
我们开启表中的TEXT IN ROW 看看发生了什么
exec sp_tableoption Hastext,'text in row',500
--查看DATA页面
dbcc page(tempdb,1,126,1)
--发现结果跟不开启前一样那是因为要使在LOB页面上的数据转移到DATA页面必须更新文本
update Hastext
set COL3=REPLICATE('k',250)
--再次查看
dbcc page(tempdb,1,126,1)
/*
00000000: 30000700 41414104 00800300 15000f01 ?...AAA.........
00000010: 12014242 426b6b6b 6b6b6b6b 6b6b6b6b ?.BBBkkkkkkkkkkk
00000020: 6b6b6b6b 6b6b6b6b 6b6b6b6b 6b6b6b6b ?kkkkkkkkkkkkkkk
00000030: 6b6b6b6b 6b6b6b6b 6b6b6b6b 6b6b6b6b ?kkkkkkkkkkkkkkk
00000040: 6b6b6b6b 6b6b6b6b 6b6b6b6b 6b6b6b6b ?kkkkkkkkkkkkkkk
。。。
00000100: 6b6b6b6b 6b6b6b6b 6b6b6b6b 6b6b6b43 ?kkkkkkkkkkkkkkC
00000110: 4343?8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??8224 ??C
*/
我们可以清楚看到 6b6b 也就是KK都进入了DATA页面。。
--如果我们是改变该选项的大小上限呢
exec sp_tableoption Hastext,'text in row',50
--再次查看
dbcc page(tempdb,1,126,1)
/*
Slot 0, Offset 0x60, Length 48, DumpStyle BYTE
00000000: 30000700 41414104 00800300 15002d80 ?...AAA.......-.
00000010: 30004242 42040000 62010000 00366b00 ?.BBB...b....6k.
00000020: 00fa0000 00940000 00010000 00434343 ?............CCC
*/
变化:LOB数据消失在DATA页面
变化:Length 48 而不是 . 这里多出来的个字节是什么呢?我们来对比一下这行数据和上面一开始的数据,不同点在这:
0000e5 07000000 00ad0000 00010001 00==》字节的指针
040000 62010000 00366b00 00fa0000 00940000 00010000 00 ==》这是一个根结构
这里说明当我们修改选项上限大小,对于那些大小和上限不符合的(这里指大于上限)的LOB数据,在DATA页面存储的不是一个字节的指针,而是一个至少字节的根结构
ps:增加选项的上限的大小 效果是开启一样的 需要更新文本才能转移数据
--现在我们来关闭TEXT IN ROW 看看发生了什么
exec sp_tableoption Hastext,'text in row',0
--再次查看
dbcc page(tempdb,1,126,1)
--我们可以看到DATA页面的LOB数据又消失了,length 也回到了,也就是存字节的指针
结论:
LOB类型数据在数据页面的存储分种情况:
1.当表的'text in row'选项关闭的时候,我们的LOB数据在数据页面不会保存任何具体数据,只留下个字节指针;
2.当表的'text in row'选项开启的时候,如果行的LOB数据大小大于选项上限,会留下一个至少字节的指针(B-树的根结构).
如果行的LOB数据大小小于选项上限,在行大小能限制在的前提下,可以将LOB数据存储在数据页面,否则只能把LOB数据推到LOB页面