正如您在检查实际页面时所看到的那样,
这些行的物理位置可以位于页面的任何位置。

图片 1

  我们再来看一下DBCC PAGE(TESTDB,1,2,3)的执行结果。

图片 2

这允许您查看数据库中任何给定页的页标题、数据行和行偏移表。

图片 3

  dbname       包含页面的数据库的名称

 http://support.microsoft.com/?scid=kb%3Ben-us%3B83065&x=8&y=12

中间部分包含存储在页面上的实际数据, 每五列显示八个十六进制数字。

DBCC IND
命令用于查询一个存储对象的内部存储结构信息,该命令有4个参数,
前3个参数必须指定。语法如下:
DBCC IND ( { ‘dbname’ | dbid }, { ‘objname’ | objid },{ nonclustered
indid | 1 | 0 | -1 | -2 } [, partition_number] )
第一个参数是数据库名或数据库ID。
第二个参数是数据库中的对象名或对象ID,对象可以是表或者索引视图。
第三个参数是一个非聚集索引ID或者 1, 0, 1, or 2. 值的含义:
 0: 只显示对象的in-row data页和 in-row IAM 页。
 1: 显示对象的全部页, 包含IAM 页, in-row数据页, LOB 数据页row-overflow
数据页 . 如果请求的对象含有聚集所以则索引页也包括。
 -1: 显示全部IAM页,数据页, 索引页 也包括 LOB 和row-overflow 数据页。
 -2: 显示全部IAM页。
 Nonclustered index ID:显示索引的全部 IAM页, data页和索引页,包含LOB和
row-overflow数据页。
为了兼容sql server
2000,第四个参数是可选的,该参数用于指定一个分区号.如果不给定值或者给定0,
则显示全部分区数据。
和DBCC PAGE不同的是, SQL Server运行DBCC
IND不需要开启3604跟踪标志.

  这两个数据文件是实实在在的操作系统文件,其中一个是叫行数据文件,用来存储数据库的各种对象,另外一个是日志文件,从来记录数据变化的过程。

图片 4

 

8 * 1024 =
页的总大小,8K

                            0:默认值,输出缓冲区的标题和页面标题

查询结果分为四部分:BUFFER、PAGE HEADER、DATA、和OFFSET
TABLE
(即真实的offset array) ,

在 DBCC 页的输出中, 您可以看到此页包含23行, 第一行 (由插槽0指示)
从偏移量 1585 (0x631) 开始。

图片 5

 
  最后让我们用Internals Viewer插件看一下SGAM页的全貌吧。

正如上图所示,每个data page (除去96 bytes,还有8096 bytes存放data,row
overhead和row offset)。你可以使用下面的DBCC Page命令来查看。

数据页是包含已添加到数据库表中的用户数据的结构。

再来看下页面相关分配情况:

  总结一下,关于GAM和SGAM页比较困难的地方:

 
注意,要想得到类似上图的查询的明细信息,必须选择打开TRACEON开关,语法为:

 

数据页由3个部分组成。页头(标头),数据区(数据行和可用空间)及行偏移数组。

  PAGE HEADER这部分内容只有通过DBCC
PAGE(TESTDB,1,2,2)即整体输出页面才能够展现;通过与上面表格的对照,我们勉强能识别一些相关存储信息;当这部分缺乏官方文档的支持,为了避免无谓的猜测,所以暂时就不做深入探讨了。

CREATE TABLE dbo.Demotable2010( 
               int PKID,not null
               emp_fname  varchar(10)   NOT NULL, 
               phone      char(12)      NOT NULL, 
               job_level  smallint      NOT NULL 
);

每行在这个数组中都有一个2字节的条目 (正如前面所讨论的,
当您阅读每行所需的10个开销字节时)。

         96 = 页头大小 96
bytes       

  SGAM页面

后一篇我们将继续学习固定长度的行和可变长度的行的存储。真累啊!

图片 6

现在我们已经知道了页的结构,我们一起来小结下。

 
   以下为DBCC
PAGE(TESTDB,1,3,3)得到的相关信息,有兴趣的可以和20ee20做一下对比。

下表显示了表数据行的存储信息:

如前所述, 数据页有三种, 每个都以不同的格式存储数据。

SQL
Server会给我们包含4个部分的输出。第1部分是BUFFER,里面是一些内存分配信息,对此我们没多少兴趣。下一部分是固定96
bytes大小的页头(page header),页头(page
header)会类似如下显示:

  PAGE HEADER部分:

 Page Header的下面是row data,单个数据行最大可以存放8060 bytes的in-row
data,这就是以前数据行不能超过8060限制的原因!有些行也可以在独立的页面(pages)中存放row-overflow
data和LOB数据,存储在一个给定的page变量中的行数取决于表结构及数据被存放的结构。一个拥有全部固定长度列的表每页能存储相同的行数。一个拥有可变长度列的表在页中存放不同的行数以适应数据的实际长度。保持行长度尽量短,允许更多的行以适应页面,减少了I/O,改善了高速缓存命中率(cache-hit
ratio)。

相反, 偏移量数组中的插槽0引用聚集索引键顺序中的第一行, 插槽1引用第二行,
依此类推。

图片 7

  具体参数描述如下:

其中,最后一个参数可以是0,1,2,3,默认为0,有兴趣的朋友可以比较下这个参数的区别。我们作个示例:

清单6-4 中的代码和结果显示来自 DBCC 页的示例输出, 其 printopt 值为1。

     7 * 2 =
每条记录的系统行开销 * 记录数

图片 8
 

 其中:状态位A包含一个关于行的位图信息。这个bits有如下含义:

 

 图片 9

  7、 GAM和SGAM的区信息的字节是通过二级制反转得到的。

 

可以使用 DBCC 页命令查看数据页的内容, 

1 DBCC TRACEON(3604)
2 DBCC PAGE(InternalStorageFormat,1,79,3)
3 GO    

  SQL
Server能够迅速地锁定一个文件中的GAM页面,因为它总是位于任何数据库文件的第三页上(页码为2)。SGAM页面是在第四页上(页码为3)。下一个GAM页面出现在第一个GAM页面(页码为2)以后的每511
230个页面中,并且下一个SGAM页面出现在第一个SGAM页面(页码为3)以后的每511
230个页面中。每一个数据库文件的页码为0的页面是文件头页面,并且每个文件仅有一页。页码0是头文件页,页码1是页面自由空间页(Page
Free Space,PFS)。

      Bit 0 Versioning information; in SQL Server 2008, it’s always 0.
      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.

使用具有 printopt 值1或3的 DBCC 页表示插槽位置,
即每行的6个表存储257、页上的行的偏移量和行的长度。

  • 1 Data page
    堆表和聚集索引的叶子节点数据
  • 2 Index page
    聚集索引的非叶子节点和非聚集索引的所有索引记录

  • 3 Text mixed page
    A text page that holds small chunks of LOB values plus internal
    parts of text tree. These can be shared between LOB values in the
    same partition of an index or heap.

  • 4 Text tree page A
    text page that holds large chunks of LOB values from a single column
    value.

  • 7 Sort page
    排序时所用到的临时页,排序中间操作存储数据用的。

  • 8 GAM
    page

    全局分配映射(Global Allocation Map,GAM)页面
    这些页面记录了哪些区已经被分配并用作何种用途。

  • 9 SGAM
    page

    共享全局分配映射(Shared Global Allocation Map,GAM)页面
    这些页面记录了哪些区当前被用作混合类型的区,并且这些区需含有至少一个未使用的页面。

  • 10
    IAM page
     有关每个分配单元中表或索引所使用的区的信息

  • 11 PFS
    page

     有关页分配和页的可用空间的信息

  • 13 boot page
    记录了关于数据库的信息,仅存于每个数据库的第9页

  • 15 file header
    page 
    记录了关于数据库文件的信息,存于每个数据库文件的第0页

  • 16 DCM
    page

    记录自从上次全备以来的数据改变的页面,以备差异备份

  • 17 BCM
    page
     有关每个分配单元中自最后一条
    BACKUP LOG 语句之后的大容量操作所修改的区的信息

  数据库被分成若干逻辑页面(每个页面8KB),并且在每个文件中,所有页面都被连续地从0到x编号,其中x是由文件的大小决定的。我们可以通过指定一个数据库ID、一个文件ID、一个页码来引用任何一个数据页。每个数据页则用来存储表和索引,以及相关的数据库管理信息。

2、Data Rows for in-Rows

 

图片 10

  4、 GAM页中0代表已分配,1代表自由区;和一般的标志位的含义刚好相反。

行偏移数组(row offset array) 是一个2-byte
entries的块(block),每个项说明对应数据行在页开始的偏移,每行(row)有一个两字节的项。尽管这些字节不会和数据一起存储在行中,它们能影响适应page的行数。行偏移数组揭示了行在页上的逻辑顺序。比如,如果一个表有一个聚集索引,SQL
Server按聚集索引键的顺序存放数据。这并不意味着数据是物理按聚集索引键的顺序存放,而是行偏移数组的Slot
0 指向聚集索引键序列的第一行(row),Slot 1
指向第二行,等等。当我们要快速查看实际页的时候,这些行的物理位置可能在页的任何位置。

查看数据页

这个行偏移表,应该从下往上读。每条槽条目是一个2
bytes长的指针指向页里槽偏移量。这里我们插入了2条记录,所以表里有2个槽条目。第1条记录指向第96
bytes,刚好在页头后。这个行偏移表可以帮助我们管理页面的记录。在页里的行偏移表里,每条记录需要2
bytes的大小来存储。于此类似,在堆表上建立的非聚集索引,每个非聚集索引行里都包含一个物理指针映射回堆表里的行记录。这个物理指针是[文件号:页号:槽号](file:page:solt)的结构,因此在读取页的时候,可以找到堆表里的对应行,再通过行偏移表里槽号里的偏移量,就可以在页里读取到对应的行记录。如果我们要修改页中间的记录,我们并不一定需要重组整个页,我们只要修改偏移表里偏移量即可。

  在SQLServer2008的每一个数据库中的前八页顺序都是固定的。

比如你想得知系统硬件的相关信息,可以通过DBCC
traceON(3205)打开跟踪开关。
 

 

页的最后一部分是行偏移数组表,我们可以用参数为1的DBCC
PAGE命令来,在输出信息的底部获得。

第8页

查询结果如下:

 

  • GAM (1:2) = ALLOCATED
                                                   
      在GAM页上的分配情况
  • SGAM (1:3) = ALLOCATED
                                                 
      在SGAM页上的分配情况
  • PFS (1:1) = 0x61
    MIXED_EXT ALLOCATED 
    50_PCT_FULL 在PFS页上的分配情况,该页为50%满,                       

  • DIFF (1:6) =
    CHANGED

  • ML (1:7) = NOT
    MIN_LOGGED   

  我们顺着上面数据文件的路径可以找到该文件,观察一下新建的数据文件的大小为:

DBCC traceON(3604)
GO

在给定页上存储的行数根据表结构和存储的数据而变化。

在页头我们看到当前页面还有7644
bytes可以用,我们一起来验证下。

  从逻辑角度而言,数据库的最小存储单位为页即8kb。

 http://support.microsoft.com/?scid=kb%3Ben-us%3B83065&x=15&y=13http://blogs.msdn.com/sqlserverstorageengine/archive/2006/12/13/More-undocumented-fun\_3A00\_-DBCC-IND\_2C00\_-DBCC-PAGE\_2C00\_-and-off\_2D00\_row-columns.aspx

 

 217 * 2 = 每条记录的总长
* 记录数

       关于数据库页类型如下所示:

 

 

 

 

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

图片 11

接下来就是用于存放实际数据的槽(slot),每条记录存放一个槽(slot)里。0号槽在页里拥有第1条数据,1号槽拥有第2条数据,以此类推。通过下面的图片,你可以看到我们记录大小是224
bytes,217 bytes(50+50+100+5+4+8) 的定长和7 bytes
的系统行开销。

BUF @0x03585CD8 每一次清空缓存再次查询,地址都会改变
bpage = 0x060B4000 每一次清空缓存再次查询,地址都会改变
bhash = 0x00000000 相对不变
bpageno = (1:2) 当前页面地址
bdbid = 8 sys.databases.database_id
breferences = 1 每一次清空缓存再次查询,地址都会改变
bUse1 = 41490 每一次清空缓存再次查询,地址都会改变
bstat = 0xc00009 相对不变
blog = 0x59ca2159 相对不变
bnext = 0x00000000 相对不变

首先存储的是pkid,再是phone,job_level,最后才是 emp_fname,因为它是可变长度的。

页标题后面是存储表实际数据行的区域。单个数据行的最大大小为8060字节的行内数据。

(8 * 1024) – 96 – (217 *
2)-(7 * 2)-(2 * 2)=7644 bytes

  最后让我们用Internals Viewer插件看一下GAM页的全貌吧。

3、Row Offset Array

 

我们都很清楚SQL Server用8KB
的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行。也就是说,SQL
Server
读取或写入所有数据页。页有不同的类型,像数据页,GAM,SGAM等。在这文章里,让我们一起来理解下数据页结构。

【IT168专稿】谈到GAM和SGAM,我们不得不从数据库的页和区说起。一个数据库由用户定义的空间构成,这些空间用来永久存储用户对象,例如数据库管理信息、表和索引。这些空间被分配在一个或多个操作系统文件中。

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

 

执行如下的命令:

                          
2:输出缓冲区的标题、页面标题(整体输出页面),以及行偏移量表

1、Page Header

Author

发表评论

电子邮件地址不会被公开。 必填项已用*标注