《Microsoft Sql server 2008 Internals》读书笔记--第五章Table(5)

 《Microsoft Sql server 2008 Internals》读书笔记订阅地址:

http://www.cnblogs.com/downmoon/category/230397.html/rss

《Microsoft Sql server 2008 Internals》索引目录:

《Microsoft Sql server 2008 Internal》读书笔记--目录索引

 

 

前面我们学习了数据页 的存储结构以及如何检查一个data page。那么如何查询一个物理页呢?

记得在上篇文章时,我们介绍了了一个未公开的DBCC PAGE命令。该命令前需要知道页的具体参数,如
--查询testdb数据库的第一个文件的第157页的数据页
--DBCC PAGE (testdb,1,157,1);

那么,如何查询第一页(first_page)的值呢?我们来看一个例子:假定我们创建一个表Fixed,语句如下:

CREATE TABLE Fixed
(
Col1
char ( 5 ) NOT NULL ,
Col2
int NOT NULL ,
Col3
char ( 3 ) NULL ,
Col4
char ( 6 ) NOT NULL
);
INSERT Fixed VALUES ( ' ABCDE ' , 123 , NULL , ' CCCC ' );

用下列语句,可以查询Fixed表的first_page的值。

SELECT object_name ( object_id ) AS name,
rows, type_desc
as page_type_desc,
total_pages
AS pages, first_page
FROM sys.partitions p JOIN sys.system_internals_allocation_units a
ON p.partition_id = a.container_id
WHERE object_id = object_id ( ' dbo.Fixed ' );

结果为:
name    rows    page_type_desc    pages    first_page
Fixed    1    IN_ROW_DATA    2    0xEE0000000100

我们将这个十六进制结果转化一下,00 10 00 00 00 EE。

前两个group代表一个2字节的文件数。这里是0x0001,页数是00EE,十进制是。可以通过一个function来转换。

CREATE FUNCTION convert_page_nums ( @page_num binary ( 6 ))
RETURNS varchar ( 11 )
AS
BEGIN
RETURN ( convert ( varchar ( 2 ), ( convert ( int , substring ( @page_num , 6 , 1 ))
* power ( 2 , 8 )) +
(
convert ( int , substring ( @page_num , 5 , 1 )))) + ' : ' +
convert ( varchar ( 11 ),
(
convert ( int , substring ( @page_num , 4 , 1 )) * power ( 2 , 24 )) +
(
convert ( int , substring ( @page_num , 3 , 1 )) * power ( 2 , 16 )) +
(
convert ( int , substring ( @page_num , 2 , 1 )) * power ( 2 , 8 )) +
(
convert ( int , substring ( @page_num , 1 , 1 )))) )
END ;
SELECT dbo.convert_page_nums( 0xEE0000000100 );

结果为1:238

警告:first_page列并不一直是指向表的第一页。毕竟这是一个未公开的命令。

第二种获取页实际数字的方式是使用另外一个未公开的命令DBCC IND。例如:

DBCC IND(testdb, fixed, - 1 );

得到如下类似结果:

PageFID PagePID IAMFID IAMPID ObjectID IndexID PartitionNumber PartitionID iam_chain_type PageType IndexLevel NextPageFID NextPagePID PrevPageFID PrevPagePID
    1 238 1 239 1029578706 0 1 72057594041925632 In-row data 1 0 0 0 0 0

第三种方式是使用一个未公开的function:sys.fn_PhysLocFormatter

SELECT sys.fn_PhysLocFormatter ( %% physloc %% ) AS RID, * FROM Fixed;

结果:
RID    Col1    Col2    Col3    Col4
(1:60928:0)    ABCDE    123    NULL    CCCC 
请注意这个结果有所不同。

下面将分别介绍五种类型的存储方式:

一、固定长度的行;二、可变长度的行;三、Null和可变长度列;四、时间和日期数据;五、SQL_variant 数据

首先,我们来看第一种:固定长度的行的存储。

我们以前面创建的Fixed表为例:

一旦表被创建,我们可以从目录视图中查看到相关列的信息;

SELECT object_id , type_desc,
indexproperty ( object_id , name, ' minlen ' ) as min_row_len
FROM sys.indexes where object_id = object_id ( ' Fixed ' );

SELECT column_id, name, system_type_id, max_length as max_col_len
FROM sys.columns
WHERE object_id = object_id ( ' Fixed ' );

结果:

object_id type_desc min_row_len
1029578706 HEAP 22

column_id name system_type_id max_col_len
1 Col1 175 5
2 Col2 56 4
3 Col3 175 3
4 Col4 175 6

注意:sysindexes目录视图包含列minlen和xmaxlen,存储了行的最小和最大长度。在Sql Server2008中,这些值在任何视图中是不可用的,除非你通过一个未公开的function:indexproperty读取它。对于一个只包含固定长度的列的表来说,indexproperty函数通过传入的minlen返回值等于列长度的总和(从sys.columns.max_length)加上4个字节。它不包含列数目的两个字节和用于null位图的字节。

通过以下语句可以查看列的偏移量:

SELECT c.name AS column_name, column_id, max_inrow_length,
pc.system_type_id, leaf_offset
FROM sys.system_internals_partition_columns pc
JOIN sys.partitions p
ON p.partition_id = pc.partition_id
JOIN sys.columns c
ON column_id = partition_column_id
AND c. object_id = p. object_id
WHERE p. object_id = object_id ( ' fixed ' );
Col1 1 5 175 4
Col2
2 4 56 9
Col3
3 3 175 13
Col4
4 6 175 16

对了,如何显示Buffer数据,请参看上篇内容
简要说明:

1、第一个字节:状态位A是0x10显示bit4打开,bit5未打开。我们得知该行没有可变长度列。

2、第二个字节未使用。

3、第三和第四字节是0x16等于22,显示了固定长度的列长度之和。

4、各列的偏移量分别为4,9,13,16。

5、第22字节处是0400,表明列数为4

6、null bitmap未使用。

说实话,这节和下节是本书第二难理解的内容。最难理解的内容要数第七章了。呵呵。邀月确实有点半生不熟。共同学习是我的目的。

你可能感兴趣的:(SQL Server 2008)