《Microsoft Sql server 2008 Internals》读书笔记--第五章Table(4)
《Microsoft Sql server 2008 Internals》索引目录:
《Microsoft Sql server 2008 Internal》读书笔记--目录索引
上篇我们主要学习了元数据(metadata)的存储及利用目录视图来查询这些信息,今天,我们继续学习数据页(Data Pages)。
数据页(Data pages)是包含已经添加到数据库的表中的用户数据的结构。正如前面所看到的,数据页有三类,每类数据页以不同的方式存储数据。复习一下,分别是in-row data pages、row-overflow data pages和LOB data pages。与其它类型的page一样,data pages也是固定的8K大小或8192 bytes。它由三类组件组成:the page Header,data rows和the row offset array,如下图所示:
1、Page Header
正如上图所示,每个data page (除去96 bytes,还有8096 bytes存放data,row overhead和row offset)。你可以使用下面的DBCC Page命令来查看。
2、Data Rows for in-Rows
Page Header的下面是row data,单个数据行最大可以存放8060 bytes的in-row data,这就是以前数据行不能超过8060限制的原因!有些行也可以在独立的页面(pages)中存放row-overflow data和LOB数据,存储在一个给定的page变量中的行数取决于表结构及数据被存放的结构。一个拥有全部固定长度列的表每页能存储相同的行数。一个拥有可变长度列的表在页中存放不同的行数以适应数据的实际长度。保持行长度尽量短,允许更多的行以适应页面,减少了I/O,改善了高速缓存命中率(cache-hit ratio)。
因此,作为系统架构师或数据库Designer,实在有必要了解这些啊。邀月深有体会。呵呵。程序很烂,是后天的,但数据结构不合理,那是先天的,两者的杀伤力同样惊人!
3、Row Offset Array
行偏移数组(row offset array) 是一个2-byte entries的块(block),每个项说明对应数据行在页开始的偏移,每行(row)有一个两字节的项。尽管这些字节不会和数据一起存储在行中,它们能影响适应page的行数。行偏移数组揭示了行在页上的逻辑顺序。比如,如果一个表有一个聚集索引,SQL Server按聚集索引键的顺序存放数据。这并不意味着数据是物理按聚集索引键的顺序存放,而是行偏移数组的Slot 0 指向聚集索引键序列的第一行(row),Slot 1 指向第二行,等等。当我们要快速查看实际页的时候,这些行的物理位置可能在页的任何位置。
检查数据页(Exampling Data Pages)
DBCC page命令可以帮我们查询:MSDN文档中中没有提供此命令,微软真的很那个啊。语法为:
其中,最后一个参数可以是0,1,2,3,默认为0,有兴趣的朋友可以比较下这个参数的区别。我们作个示例:
go
--查询testdb数据库的第一个文件的第157页的数据页
DBCC PAGE (testdb,1,157,1);
GO
查询结果如下:
此外,还有更详细的第X到第X行的数据显示。更多信息,请查看:
http://support.microsoft.com/?scid=kb%3Ben-us%3B83065&x=8&y=12
查询结果分为四部分:BUFFER、PAGE HEADER、DATA、和OFFSET TABLE(即真实的offset array) ,
注意,要想得到类似上图的查询的明细信息,必须选择打开TRACEON开关,语法为:
GO
关于DBCC TRACEON (Transact-SQL)的更多用法,请参考MSDN
http://msdn.microsoft.com/en-us/library/ms187329.aspx
比如你想得知系统硬件的相关信息,可以通过DBCC traceON(3205)打开跟踪开关。
数据行的结构(the structure of data rows)
一个表的通用结构如下图所示:
其中:状态位A包含一个关于行的位图信息。这个bits有如下含义:
Bits 1 through 3 Taken as a 3-bit value, 0 indicates a primary record, 1 indicates a forwarded record, 2 indicates a forwarded stub, 3 indicates an index record, 4 indicates a blob fragment, 5 indicates a ghost index record, and 6 indicates a ghost data record.
Bit 4 Indicates that a NULL bitmap exists; in SQL Server 2008, a NULL bitmap is always present, even if no NULLs are allowed in any column.
Bit 5 Indicates that variable-length columns exist in the row.
Bits 6 Indicates that the row contains versionings information.
Bits 7 Not used in SQL Server 2008.
状态位B字段中只使用一位,表示该记录是一条备份转发记录。
下表显示了表数据行的存储信息:
Information |
Mnemonic |
Size |
---|---|---|
Status Bits A |
TagA |
1 byte |
Status Bits B (not used in SQL Server 2008) |
TagB |
1 byte |
Fixed-length size |
Fsize |
2 bytes |
Fixed-length data |
Fdata |
Fsize --4 |
Number of columns |
Ncol |
2 bytes |
NULL bitmap(1 byte for each column in table; 1 indicates that the corresponding column is NULL) |
Nullbits |
Ceiling (Ncol / 8) |
Number of variable-length columns |
VarCount |
2 bytes |
Variable column offset array |
VarOffset |
2 * VarCount |
Variable-length data |
VarData |
VarOff[VarCount] |
有趣的是,当你创建一个表的时候,固定长度的列是先被存储的,比如这样一个语句
int PKID,not null
emp_fname varchar(10) NOT NULL,
phone char(12) NOT NULL,
job_level smallint NOT NULL
);
首先存储的是pkid,再是phone,job_level,最后才是 emp_fname,因为它是可变长度的。
后一篇我们将继续学习固定长度的行和可变长度的行的存储。真累啊!