348978940 发表于 2012-8-23 10:38:17

数据页的基础知识

  SQL Server 中数据存储的基本单位是页(Page)。数据库中的数据文件(.mdf 或 .mdf)分配的磁盘空间可以从逻辑上划分成页(从 0 到 n 连续编号)。磁盘 I/O 操作在页级执行。也就是说,SQL Server 每次读取或写入数据的最少数据单位是数据页。
  注意:日志文件不是用这种方式存储的,而是一系列日志记录。
  数据库被分成逻辑页面(每个页面8KB),并且在每个文件中,所有页面都被连续地从0到x编号,其中x是由文件的大小决定的。我们可以通过指定一个数据库ID、一个文件ID、一个页码来引用任何一个数据页。当我们使用ALTER DATABASE命令来扩大一个文件时,新的空间会被加到文件的末尾。也就是说,我们所扩大文件的新空间第一个数据页的页码是x+1。当我们使用DBCC SHRINKDATABASE或DBCC SHRINKFILE命令来收缩一个数据库时,将会从数据库中页码最高的页面(文件末尾)开始移除页面,并向页码较低的页面移动。这保证了一个文件中的页码总是连续的。
  在 SQL Server 中,页的大小为 8 KB。这意味着 SQL Server 数据库中每 MB 有 128 页。依次类推。根据数据库的文件大小,我们可以算出数据库有多少数据页。
  SQL Server 2005 有以下几种页类型:
页类型        内容
Data        当 text in row 设置为 ON 时,包含除 text、 ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 数据之外的所有数据的数据行。
Index        索引条目。
Text/Image        大型对象数据类型:
text、 ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 数据。
数据行超过 8 KB 时为可变长度数据类型列:
varchar、nvarchar、varbinary 和 sql_variant
Global Allocation Map、Shared Global Allocation Map        有关区是否分配的信息。
Page Free Space        有关页分配和页的可用空间的信息。
Index Allocation Map        有关每个分配单元中表或索引所使用的区的信息。
Bulk Changed Map        有关每个分配单元中自最后一条 BACKUP LOG 语句之后的大容量操作所修改的区的信息。
Differential Changed Map        有关每个分配单元中自最后一条 BACKUP DATABASE 语句之后更改的区的信息。
  数据页(Data 类型页)的结构示意图:
  每页的开头是 96 字节的标头,用于存储有关页的系统信息。此信息包括页码、页类型、页的可用空间以及拥有该页的对象的分配单元 ID。
  在数据页上,数据行紧接着标头按顺序放置。页的末尾是行偏移表,对于页中的每一行,每个行偏移表都包含一个条目。每个条目记录对应行的第一个字节与页首的距离。行偏移表中的条目的顺序与页中行的顺序相反。
  

怎样查看表的数据页的结构
作者: ,  出处:blog, 责任编辑: 李书琴, 
2008-01-28 03:04
  本文教你怎样查看表的数据页的结构……
  SQLServer2000提供了一个读取数据页结构的命令DBCC Page。该命令为非文档化的命令,具体如下:
  DBCC Page ({dbid|dbname},filenum,pagenum[,printopt])
  具体参数描述如下:
  dbid 包含页面的数据库ID
  dbname 包含页面的数据库的名称
  filenum 包含页面的文件编号
  pagenum 文件内的页面
  printopt 可选的输出选项;选用其中一个值:
  0:默认值,输出缓冲区的标题和页面标题
  1:输出缓冲区的标题、页面标题(分别输出每一行),以及行偏移量表
  2:输出缓冲区的标题、页面标题(整体输出页面),以及行偏移量表
  3:输出缓冲区的标题、页面标题(分别输出每一行),以及行偏移量表;每一行
  后跟分别列出的它的列值
  要想看到这些输出的结果,还需要设置DBCC TRACEON(3604)。
  对于表来说,它所在的dbid或者dbname很容易知道,那么它的filenum和pagenum怎么知道呢?其实这个值存在系统表sysindexes的列first中(当indid为0或者1时,indid为0表示该表是一个堆表,没有任何聚集索引,indid为1表示该索引为聚集索引),列first的数据类型为binary(6),它是以16进制的形式储的,需要进行转换。在16进制中,每两个16进制数字表示一个字节,并且是逆序排列的。比如假设一个表的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的值
  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的数据页了。怎么读懂这些输出结果呢?
  DBCC Page的输出主要分为5个部分: Page、BUFFER、Page Hearder、Data、OFFSET Table(行的偏移量数组)。
  Page指出该表的文件编号及页码。
  Buffer指出关于给定页面的缓冲区的信息。
  Page Header指出页面中所有标题字段的数据。
  Data指出每一行的信息。对于每一行,DBCC Page指出行在槽中的位置,以及该行在页面中的偏移量。页面数据被分成3部分,左列指出的是所显示的数据在行中的字节位置。接着4列包含页面存储的实际数据,以16进制的形式显示。右列包含数据的字符表示(只有字符数据是可读的)。
  Offset Table指出页面末尾的行偏移量数组的内容。注意这里并不是行物理存储的顺序,而是以槽的编号的顺序来显示的,不过这里可以通过槽的编号看出它的物理存储顺序,比如槽的编号最小的为物理存储的第一行,依此类推。

yogevic 发表于 2012-8-23 10:54:18

好东西,好人,比那些动不动就要10分的人简直好到不行了!

jj940 发表于 2012-8-23 19:31:52

学习了,太感谢了
页: [1]
查看完整版本: 数据页的基础知识