目录
一、内部存储概述
二、 数据行(记录)结构
1、定长记录
2、变长记录
一、内部存储概述
表是有关某个特定实例的数据集合,在关系数据库中处于核心地位。
创建一个表,就会有一行或多行插入到用来管理这个表的多个系统表里。至少要写信息到sysobjects、sysindexes和syscolumns这三个系统表里,当新建的表有外码约束时,相关的信息还会插入到sysrefrences系统表里。
- Sysobjects主要记录新表的基本信息,如表名、对象ID以及表的所有者等等。
- Syscolumns主要记录新表列的信息,如列名、类型和长度等。
- Sysindexes系统表记录包含指向新表所使用的存储空间的指针和有关新表大小的信息。
- sysrefrences系统表里记录参照表的外键信息。
注意:
- 当一个新表刚创建时,在插入第一行数据之前系统不会立即为其分配存储空间,因此Sysindexes表中指示页地址和预留存储空间的列将都是0值。
- 如果在该表上定义了PRIMARY KEY或UNIQUE约束,而PRIMARY KEY或UNIQUE约束的背后是由簇集索引支持的,则该表在Sysindexes中对应行的indid值为1。
- 任何有非簇集索引支持的其他约束在Sysindexes表中都有一行,而且该行的indid值在2到250之间。
二、 数据行(记录)结构
1、定长记录
在定长记录里,每个字段都有固定的长度,而且字段数也是固定的。这种记录的字段能够连续存储,因此在给定记录地址的情况下,借助系统目录里有关字段的长度信息就能计算出某个特殊字段的的地址。
2、变长记录
对于变长记录来说,一种可能的记录组织方式就是像定长记录一样连续地存放字段,字段之间通过分割符隔开。这种组织方式需要扫描记录才能定位需要访问的字段。
另一种方法是在记录开始处预留一些空间作为存放一个整数偏移量数组的空间,数组中的第I个整数表示记录的第I个字段的其始地址,当然这个地址是相对于记录的起始地址的。另外在数组中也存储记录尾部的偏移量,这个偏移量用来识别最后一个字段的结束位置。
SQL Server定长记录的存储
首先来看最简单的情况,记录中所有字段都是定长的。
CREATE TABLE Fixed
(
col1 int NOT NULL
col2 char(5) NOT NULL
col3 char(3) NULL
col4 float NOT NULL
)
当这个表被创建以后,就有类似下面一个记录被插入到sysindexes系统表中:
id | name | indid | first | minlen |
2099048 | Fixed | 0 | 0x000000000000 | 24 |
而其各个字段则会被插入到syscolumns系统表中:
name | colid | xtype | length | xoffset |
col1 | 1 | 56 | 4 | 4 |
col2 | 2 | 175 | 5 | 8 |
col3 | 3 | 175 | 3 | 13 |
col4 | 4 | 62 | 8 | 16 |
当往Fixed表中插入一个记录数据时,例如:
INSERT INTO Fixed VALUES(123,‘ABCD’,NULL,45.5)
Fixed表在sysindexes系统表里的内容就会发生变化:
id | name | indid | first | minlen |
2099048 | Fixed | 0 | 0x720000000000 | 24 |
这说明在插入了一记录数据之后,SQL Server就为Fixed表分配了一个数据页。Fixed表只包含四个定长字段,sysindexes表中minlen字段的值表示记录的最小长度,该长度恰好是syscolumns表中表示字段长度的length的数字之和再加上4个字节。其中额外的4个字节是用于记录字段数目的两个字节和表示字段中NULL的字节数。
第一个字节是状态位A,它的值是0x10,表示只有位4是1,其他位都是0,因此该记录没有变长字段(如果位5为1说明存在变长字段)。
最后一个字节是NULL位图,其值4意味只有第三位是1,表示第三个字段是NULL。
SQL Server变长记录的存储
CREATE TABLE Variable
(
col1 char(3) NOT NULL
col2 varchar(15) NOT NULL
col3 varchar(5) NULL
col4 varchar(10) NOT NULL
col5 smallint NOT NULL
)
当这个表被创建以后,就有类似下面一个记录被插入到sysindexes系统表中:
id | name | indid | first | minlen |
18099105 | Variable | 0 | 0x000000000000 | 9 |
而其各个字段则会被插入到syscolumns系统表中:
name | colid | xtype | length | xoffset |
col1 | 1 | 175 | 3 | 4 |
col2 | 2 | 167 | 15 | -1 |
col3 | 3 | 167 | 5 | -1 |
col4 | 4 | 167 | 10 | -1 |
col5 | 5 | 52 | 2 | 7 |
当往Variable表中插入一个记录数据时,例如:
INSERT INTO Variable VALUES(‘xyz’,‘ABCDe’,NULL, ‘123’,999)
Variable表在sysindexes系统表里的内容就会发生变化:
id | name | indid | first | minlen |
18099105 | Variable | 0 | 0x880000000000 | 9 |
定长字段的数据位于记录中由syscolumns的xoffset值指定的字节偏移量所在的位置,即col1起始于字节偏移量4的位置,而col5起始于字节偏移量7的位置。
为了找到变长字段,首先要确定记录中列偏移数组的位置。在表示总字段数的2个字节(其值是0500)和表示位图的1字节(其值为04)之后就是变长字段数的两个字节,在本例中其值是0300,换算成十进制是3,说明该记录有3个变长字段存在。紧跟其后的字节就是变长字段偏移数组。该例变长字段偏移数组用三个2字节来表示3个变长字段在记录中的结束位置。1900经过字节交换是0x0019,所以第一个变长字段结束于25字节处。接下来也是0x0019,所以第二个变长字段实际长度为0,表明没有任何东西存储在变长数据区域。1c00经过字节交换是0x001c,所以第三个变长字段结束于28字节处,而且整个记录也结束于28字节处,换句话说,目前整个记录的实际长度是28个字节长。