日期:2014-05-18  浏览次数:20371 次

【SQL SERVER 2005页面存储之--表的数据行在页中的存储 】
由于帖子无法良好排版
请进入博客看全文内容
http://blog.csdn.net/feixianxxx/archive/2010/03/17/5390317.aspx

SQL code
第一篇来说说我们的表的行数据在页中的存储详解,也为接下来几篇关于特殊数据类型存储和索引的存储
这篇讲得是没有聚集索引,没有非聚集索引,含有定长列和变长列的堆

/*----------------------------------
*auther:Poofly
*date:2010.3.14
*VERSION:
    Microsoft SQL Server 2008 (RTM) - 10.0.1600.22 (Intel X86) 
    Jul  9 2008 14:43:34 
    Copyright (c) 1988-2008 Microsoft Corporation
    Enterprise Evaluation Edition on Windows NT 6.1 <X86> (Build 7600: )
*转载请注明出处
*更多精彩内容,请进http://blog.csdn.net/feixianxxx
------------------------------------*/
--建立测试表
create table t_test
(
    col1 int,
    col2 varchar(10),
    col3 datetime,
    col4 char(10),
    col5 nvarchar(4)
)
go
--插入数据
insert t_test values(1,'ABC','2010-03-15','123',N'abc')
insert t_test values(2,'DEF',CURRENT_TIMESTAMP,'4567',N'defg')
go
--接下来说说读取信息的一般步骤:
1.我们要查看页面分布情况,可以使用DBCC IND('dbname'|dbid,'objectname'|objectID,nonclustered indid|1|0|-1|-2[,partition_number])
    --找到各个类型的页面分布和它们的所在的文件号和页号.
      {'dbname'|dbid}-数据库名/数据库ID
      {'objectname'|objectID}->对象名/对象ID
      {nonclustered indid|1|0|-1|-2}->0 显示行内数据分页及指定对象的行内IAM分页信息
                                      1 显示所有分页的信息,包括IAM分页,数据分页,所有存在的LOB分页和行溢出页,索引分页
                                      -1 显示所有IAM、数据分页、及指定对象上全部索引的索引分页.
                                      -2 显示指定对象的所有IAM分页
                                      非聚集索引的ID 显示所有的IAM、数据分页以及一个索引的索引分页信息。
      {partition_number}->可选,为了与2000中的DBCC IND命令向前兼容.它指定了一个特定分区号,如果不指定,显示所有分区的信息
      --介绍完后,我们来使用这个DBCC IND的命令
      DBCC IND(poofly,t_test,1)
      --我们发现输出了很多的列名,这样的输出无法让我们有所选择过滤自己想要的.所以采取技术内幕上所用的insert exec的方法将信息导入表中后进行查看(这也是后几篇将用到的手段)
      --首先创建信息表(这个表之后几篇会一直用到)
      CREATE TABLE sp_table_pages
    (PageFID  tinyint, 
      PagePID int,   
      IAMFID   tinyint, 
      IAMPID  int, 
      ObjectID  int,
      IndexID  tinyint,
      PartitionNumber tinyint,
      PartitionID bigint,
      iam_chain_type  varchar(30),    
      PageType  tinyint, 
      IndexLevel  tinyint,
      NextPageFID  tinyint,
      NextPagePID  int,
      PrevPageFID  tinyint,
      PrevPagePID int, 
      Primary Key (PageFID, PagePID));
    GO
    --接着将输出结果导入表中
    TRUNCATE TABLE sp_table_pages;
    INSERT INTO sp_table_pages
        EXEC ('DBCC IND(poofly,t_test,1)'  );
    GO
    SELECT PageFID, PagePID, indexID,IndexLevel, PageType FROM sp_table_pages
    /*
    PageFID PagePID     indexID IndexLevel PageType
    ------- ----------- ------- ---------- --------
    5       1119        0       0          1
    5       1168        0       NULL       10
    */
    --在我们的输出结果中可以看到我们的文件号及对应的页号,当然也看到了页面的类型。
       indexID->0 代表堆, 1 代表聚集索引的分页, 2-250 代表非聚集索引的分页
       IndexLevel->索引的层次 0 代表叶级别分页 >0 代表非叶级别层次 NULL 代表IAM分页
       PageType->分页类型 1=数据页面 2=索引分页 3=LOB_MIXED_PAGE 4=LOB_FREE_PAGE 10=IAM分页
    则上面的第一条记录就表示5号文件1119页是一个堆上的在叶级别的数据页

2.运行DBCC TRACEON(3604) 这样才能让DBCC PAGE的结果输出给客户端。
    DBCC TRACEON(3604)

3.使用DBCC PAGE({dbid|dbname},filenum,pagenum[,printopt])命令读取你想要查看的页面
    关于这个命令的详细讲解,可以参看石头大大的写的http://blog.csdn.net/happyflystone/archive/2009/11/19/4834762.aspx
  --简单介绍下页面的组成
    一般的页面分成4个部分,BUFFER、PAGEHEADER、DATA、OFFSET TABLE
    BUFFER:显示了指定页面的缓冲信息。由于它是一个内存中结构,所以仅当页面处于内存中时候才有效.
    PAGEHEADER:显示指定页面的所有报头字段信息。具体内容参考影子老师写的http://blog.csdn.net/HEROWANG/archive/2009/12/11/4987066.aspx
    DATA:显示每行数据的具体存储.这里使用的Printopt不一样,显示的风格也不一样。下面重点具体分析该部分的数据读取部分.
         有关该部分显示的行类型的解读可以看石头大大写的http://blog.csdn.net/happyflystone/archive/2009/12/09/4969909.aspx。
    OFFSET TABLE:显示了所有行偏移矩阵的内容.
    说了这么多,我们具体来看看我们文章中这个表的页面吧
    dbcc page('poofly',5,1119,1)
    /*
    PAGE: (5:1119)
    BUFFER:
    <这里的内容就是BUFFER>
    PAGE HEADER:
    <这里的内容就是PAGE HEADER>
    ..我们主要是分析下面的DATA部分
    DATA:

    Slot 0, Offset 0x60, Length 44, DumpStyle BYTE

    Reco