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

本文详细介绍了如何在SQL Server 2008中查询物理页,包括使用未公开的DBCC PAGE命令及其它方法确定页位置,并深入探讨了固定长度行的存储方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

前面我们学习了数据页 的存储结构以及如何检查一个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'); 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未使用。
说实话,这节和下节是本书第二难理解的内容。最难理解的内容要数第七章了。呵呵

邀月注:本文版权由邀月和优快云共同所有,转载请注明出处。
助人等于自助! 3w@live.cn

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值