查看表的数据页的结构!

来源:互联网 发布:网络寻线仪价格 编辑:程序博客网 时间:2024/05/17 00:15
转贴:www.windbi.com

数据库中表的存储是以page为单位的,怎么查看一个表的数据页结构呢?SQLServer2000/2005
提供了一个读取数据页结构的命令DBCC Page。该命令为非文档化的命令,具体如下:

DBCC Page ({dbid|dbname},filenum,pagenum[,printopt])

具体参数描述如下:
dbid         
包含页面的数据库ID
dbname   
包含页面的数据库的名称
filenum     
包含页面的文件编号
pagenum 
文件内的页面
printopt   
可选的输出选项;选用其中一个值:
                  0:
默认值,输出缓冲区的标题和页面标题
                  1:
输出缓冲区的标题、页面标题(分别输出每一行),以及行偏移量表
                  2:
输出缓冲区的标题、页面标题(整体输出页面),以及行偏移量表
                  3:
输出缓冲区的标题、页面标题(分别输出每一行),以及行偏移量表;每一行
                   
后跟分别列出的它的列值

要想看到这些输出的结果,还需要设置DBCC TRACEON(3604)

对于表来说,它所在的dbid或者dbname很容易知道,那么它的filenumpagenum怎么知道呢?其实这个值存在系统表sysindexes的列first(indid0或者1时,indid0表示该表是一个堆表,没有任何聚集索引,indid1表示该索引为聚集索引),列first的数据类型为binary(6),它是以16进制的形式储的,需要进行转换。在16进制中,每两个16进制数字表示一个字节(Why?因为每个16进制数字可以用4个二进制数字表示(每个8进制数字可以用3个二进制数字表示,天下人都知道啊),而8个二进制数字即8位为一个字节,所以两个16进制数字即为1个字节(8进制数字不能平分,所以出现了16进制哦),例如:十六进制数字FF就可以用二进制数字表示为11111111共有8位,而天下人都知道1Byte=8Bit,所以两个16进制数字FF就占用了一个字节,呵呵,是不是很绕口,绕惯了就好了,别晕就行!),并且是逆序排列的。比如假设一个表的First的值为0xC70000000100,怎么转换呢?因为它是逆序排列的,并且每两个表示一个字节,所以每次都将剩下first值的最后两位移到转换后数据的最后,具体转换步骤如下:

步骤      此时的first                转换后的数据
0    0xC70000000100
1    0xC700000001            00
2    0xC7000000                0001
3    0xC70000                    000100
4    0xC700                        00010000
5    0xC7                            0001000000
6    0x                                0001000000C7

此时转换完成。数据0001000000C7即是我们需要的数据,其中它的前2组数(0001)表示该表所在的文件编号;后4(000000C7)表示该表所在的页码(注意该数据还要转换为10进制的数才能具体知道是多少)

完整的代码如下(将设我们要查看的是表test的数据页的结构):

--
sysindexes中取出first的值SQL2005中即为sys.sysindexes,但是同样有first字节,简直就是系统表都变成了相应的动态视图了,但是字段都照抄过来了
declare @first binary(6)
select @first = first from sysindexes where id = object_id('test') and indid in(0,1)
declare @PageNum int
select @PageNum = convert(int, substring(@first,4,1) + substring(@first,3,1) +

substring(@first,2,1) + substring(@first,1,1) )
declare @FileNum int
select @FileNum = convert(int, substring(@first,6,1) + substring(@first,5,1))
select @FileNum, @PageNum


--
执行DBCC Page
declare @sql varchar(1000)
select @sql = 'dbcc page (''' + db_name() + ''', ' + convert(varchar(10),@FileNum) + ', ' + convert(varchar(10),@PageNum) + ', 1)'
select @sql
dbcc traceon(3604)
exec (@sql)


执行完上面的语句,就可以查看表test的数据页了。怎么读懂这些输出结果呢?
代码中有很多系统函数,比如substring(),convert(),object_id()等等,具体怎么使用,查看SQL Server book online.

DBCC Page
的输出主要分为5个部分: PageBUFFERPage HearderDataOFFSET Table(行的偏移量数组)

Page
指出该表的文件编号及页码。

Buffer
指出关于给定页面的缓冲区的信息。

Page Header
指出页面中所有标题字段的数据。

Data
指出每一行的信息。对于每一行,DBCC Page指出行在槽中的位置,以及该行在页面中的偏移量。页面数据被分成3部分,左列指出的是所显示的数据在行中的字节位置。接着4列包含页面存储的实际数据,以16进制的形式显示。右列包含数据的字符表示(只有字符数据是可读的)

Offset Table
指出页面末尾的行偏移量数组的内容。注意这里并不是行物理存储的顺序,而是以槽的编号的顺序来显示的,不过这里可以通过槽的编号看出它的物理存储顺序,比如槽的编号最小的为物理存储的第一行,依此类推
Note: DBCC: Database Concurrency Checker