存储引擎-存储结构之一:行

2014-11-24 10:16:28 · 作者: · 浏览: 0
存储引擎-存储结构之一:行
SQLServer中,数据的存储是按记录行来存储的,每一行包含数据的所有的列,这样的存储,是非常有利数据的查询的,
但也正因为如此,LOB页,行溢出页,表结构修改都极易产生空洞,形成磁盘碎片。
我们做个例子分析下:
测试范围->没有聚集索引,没有非聚集索引,含有定长列和变长列的堆
create table t_test
(
col1 int,
col2 varchar(10),
col3 datetime,
col4 char(10),
col5 nvarchar(4)
)
go

--插入数据
insert t_test values(1,'ABC','2010-03-15','123',N'abc')
insert t_test values(2,'DEF',CURRENT_TIMESTAMP,'4567',N'defg')
GO

SELECT * FROM t_test

DBCC IND(test,t_test,1)
DBCC TRACEON(3604)

DBCC PAGE('test',1,1456,1)
/*

Slot 0, Offset 0x60, Length 44, DumpStyle BYTE

Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS
Record Size = 44                     
Memory Dump @0x000000000FFEA060

0000000000000000:   30001a00 01000000 00000000 3a9d0000  0...........:... 
0000000000000010:   31323320 20202020 20200500 00020026  123       .....& 
0000000000000020:   002c0041 42436100 62006300           .,.ABCa.b.c.     
*/

记录行 状态位A 状态位B 列偏移 定长数据 表总列数
NULL位图
变长列的数目 第一变长列数据终止位置 第二变长列数据终止位置 第一列变长列的数据 第二列变长列的数据
0x30 0x00 0x1a00 0x01000000-2020 2020 0x0500 0x00 0x0200 0x2600 0x2c00 0x41 4243 0x6100 62006300
说明
00110000
行属性
未启用 =26
定长数据部分
(col1,col3,col4)
=5 0 =2 =38 =44 ='ABC' ='abc'
解释:
状态位A:行属性的位图 从高位存到地位(右边第一位是bit0).
bit0:版本信息,SQL2005/08总是为
bit1-3: 0=(primary record);1=(forwarded record);2=(forwarding stud);3=(index record);4=(溢出数据);5=(ghost索引记录);6=(ghost数据记录)
bit4:表示存在NULL位图(在数据行里SQL2005/08总存在NULL位图)
bit5:表示存在变长列
bit6:未启用
bit7:表示存在幽灵记录
定长数据部分(col1,col3,col4):
01000000->00000000 00000000 00000000 00000001=1
00000000 3a9d0000->1001110100111010 0...0 =40250
31323320 20202020 2020->'123 '
ps:注意这里的col3的类型是datetime类型,这个类型在内部存贮并不是你们想象的那样.
我简单来说就是它将这个类型的存储分成个部分,date部分和time部分
我们的例子中 表示的时间部分,3a9d0000表示的时候date部分
因为第一部分time默认是:00:00 所以值为 3a9d0000换算成十进制为
你可以通过
    select CONVERT(int,SUBSTRING(CONVERT(varbinary(8),cast('2013-07-14' as datetime)),1,4)),--40250

     CONVERT(int,SUBSTRING(CONVERT(varbinary(8),cast('2013-07-14' as datetime)),5,4))—0


0500->00000000 00000101=5 表示该表有列

00->00000000 因为该表只有列 所以只需要看后面个,0表示该行的对应列不为NULL

0200->00000000 00000010=2 表示该表有列 (col2,col5)

2600->00000000 00100110=38=1+1+2+(4+8+10)+2+ceiling(5/8)+2+2+2+len('ABC')

2c00->00000000 00101100=44 因为一共就列变长列 所以它的结束位置就是行的最终长度 LENGTH 44

41 4243->01000001 01000010 01000011='ABC'

6100 62006300->01100001 00..00 01100010 00..00 01100011 00..00='abc' 这里用六个字节是因为它是NVARCHAR类型 2个字节才能存一个字符