[推荐] 【SQL SERVER 2005页面存储之--表的数据行在页中的存储 】 100feixianxxx]

发布时间:2014-1-1 0:09:48编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"[推荐] 【SQL SERVER 2005页面存储之--表的数据行在页中的存储 】 100feixianxxx]",主要涉及到[推荐] 【SQL SERVER 2005页面存储之--表的数据行在页中的存储 】 100feixianxxx]方面的内容,对于[推荐] 【SQL SERVER 2005页面存储之--表的数据行在页中的存储 】 100feixianxxx]感兴趣的同学可以参考一下。

本帖最后由 feixianxxx 于 2010-03-17 19:33:10 编辑 由于帖子无法良好排版  请进入博客看全文内容http://blog.csdn.net/feixianxxx/archive/2010/03/17/5390317.aspx 第一篇来说说我们的表的行数据在页中的存储详解,也为接下来几篇关于特殊数据类型存储和索引的存储 这篇讲得是没有聚集索引,没有非聚集索引,含有定长列和变长列的堆 /*---------------------------------------------------------------------- *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 Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS Record Size = 44                      Memory Dump @0x6301C060 00000000:   30001a00 01000000 00000000 3a9d0000 †0...........:...          00000010:   31323320 20202020 20200500 00020026 †123       .....&          00000020:   002c0041 42436100 62006300 ††††††††††.,.ABCa.b.c.              Slot 1, Offset 0x8c, Length 46, DumpStyle BYTE Record Type = PRIMARY_RECORD         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS Record Size = 46                      Memory Dump @0x6301C08C 00000000:   30001a00 02000000 121eba00 3c9d0000 †0...........<...          00000010:   34353637 20202020 20200500 00020026 †4567      .....&          00000020:   002e0044 45466400 65006600 6700††††††...DEFd.e.f.g.            OFFSET TABLE: Row - Offset                          1 (0x1) - 140 (0x8c)                  0 (0x0) - 96 (0x60)                   */ 准备工作1:应该了解下数据行的结构(索引行的结构和这个是不一样的) 状态位A 状态位B 列数目的位置   定长数据长度  表总列数 NULL位图     变长列的列数 第一变长列数据终止位置 第二... 变成列的实际数据长度  1B      1B      2B             xB           2B  CEILING(列数/8)     2B           2B                2B           xB  ps:NULL位图后面的几个字节只有当表中含有变长列的时候才会有  在看我们的数据===(1,'ABC','2010-03-15','123',N'abc') 对照着上面的结构我们来算下第一行的行长(Slot 0, Offset 0x60, Length 44, DumpStyle BYTE)  1+1+2+(4+8+10)+2+ceiling(5/8)+2+2+2+3+3*2=44    准备工作2:我们应该了解这里读的方法           1.这里的每个数字就是以十六进制存储的,也就是说2个这里的数字就代表一个字节,我们一般采取把十六进制换成二进制,然后再换成十进制读取   2.凡是存储的是字符类型的数据值,你读的时候就按顺序,一个字节一个字节读   3.存储datetime or 数字类型 内部采取先存储低位字节 我们就采取 交换字节读取(例如 0009 换成0900)   4.如果遇到状态位 NULL位图等 就采用顺序读取,当然这里的BIT位是从高到底 比如01->00000001 右边的1是BIT0  ps:关于DATA部分Record Type (行类型部分)的解析请看石头博客http://blog.csdn.net/happyflystone/archive/2009/12/09/4969909.aspx)/    下面开始具体拆分我们的数据行  状态位A:30->00110000 它是一个行属性的位图 从高位存到地位(右边第一位是bit0).          bit0:版本信息,SQL2005/08总是为0          bit1-3: 0=(primary record);1=(forwarded record);2=(forwarding stud);3=(index record);4=(溢出数据);5=(ghost索引记录);6=(ghost数据记录)          bit4:表示存在NULL位图(在数据行里SQL2005/08总存在NULL位图)          bit5:表示存在变长列          bit6:未启用          bit7:表示存在幽灵记录          回到我们的例子中,我们的bit4为1 bit5为1表示存在NULL位图及存在变长列 状态位B:00->未启用 列数的出现位置:1a00->00000000 00011010=26<就是0050出现的位置> 定长数据部分(col1,col3,col4):01000000->00000000 00000000 00000000 00000001=1<col1的值,4字节>                              00000000 3a9d0000->1001110100111010 0...0 =40250 <col3值,8字节>                              31323320 20202020 2020->'123       '<col4的值,char(10),10字节>             ps:注意这里的col3的类型是datetime类型,这个类型在内部存贮并不是你们想象的那样.                我简单来说就是它将这个类型的存储分成2个部分,date部分和time部分                 我们的例子中00000000 表示的时间部分,3a9d0000表示的时候date部分                因为第一部分time默认是00:00:00 所以值为0 3a9d0000换算成十进制为40250                具体参考我以前写的http://blog.csdn.net/feixianxxx/archive/2009/10/15/4677124.aspx 第三点                你可以通过                select CONVERT(int,SUBSTRING(CONVERT(varbinary(8),cast('2010-03-15' as datetime)),1,4)),--40250   CONVERT(int,SUBSTRING(CONVERT(varbinary(8),cast('2010-03-15' as datetime)),5,4))--0     --自己可以尝试第二条记录验证换算                              表总列数:0500->00000000 00000101=5 表示该表有5列 NULL位图:00->00000000 因为该表只有5列 所以只需要看后面5个0,0表示该行的对应列不为NULL  变长列的数目:0200->00000000 00000010=2 表示该表有2列 (col2,col5) 第一变长列数据终止位置:2600->00000000 00100110=38=1+1+2+(4+8+10)+2+ceiling(5/8)+2+2+2+len('ABC') 第二变长列数据终止位置:2c00->00000000 00101100=44 因为一共就2列变长列 所以它的结束位置就是行的最终长度 LENGTH 44 第一列变长列的数据:41 4243->01000001 01000010 01000011='ABC' 第二列变长列的数据:6100 62006300->01100001 00..00 01100010 00..00 01100011 00..00='abc' 这里用六个字节是因为它是NVARCHAR类型 2个字节才能存一个字符 第二行数据的读取留给大家实践用. 这里的OFFSET TABLE部分我想说的是它这里通过每行偏移量揭示了真正数据行的存储位置                       1 (0x1) - 140 (0x8c)                  0 (0x0) - 96 (0x60) 我们可以看到第一行数据是从96的位置开始偏移,为什么是96开始呢?因为报头的大小为96字节. 经过44字节的填充后,第二条从140开始偏移; 而且必须注意这里的槽号显示的顺序并不一定就是物理存储的顺序, 也就是说Slot 0 并不一定是物理存储的第一条,即SLOT 0对应的偏移量不一定是最小的. 下篇:SQL SERVER 2005特殊类型存储一之LOB数据类型的存储

排不好版。。 请入博文地址查看此文http://blog.csdn.net/feixianxxx/archive/2010/03/17/5390317.aspx

学习..

这个太强大了

UP 徒弟~

...................................................................

学习了..............正在理解当中,测试2000

学习了..............

好  真的很好.用到很好

本帖最后由 feixianxxx 于 2010-03-17 20:45:09 编辑

看不懂。。。。

顶一个,麦同学研究的很带劲嘛。。。。加油

强大啊

学习

学习。。。。

靠,刚发的竟然被我从google上搜到了……

顶,强,学习

学习.......

不懂,路过

...................

学习了..............

看不懂 学习。。。。

支持一个!!!~~~~~~~~~~~~~~

学习。。。。

原理很重要

mark......

看看Blog再说啦!!!!!!!!!!!!!!!!

学习了,谢谢哦!!!!

学习........

强烈学习中...

学习了........!

学习了..............正在理解当中

学习中,有空好好研究一下。

强大。。。很好 

super man

学习。。。。。。。。

学学,希望楼主再接再厉

纯支持

  每天回帖即可获得10分可用分!

理解中!!!!

.IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII

为了积分。。

好东西

非常经典的文章

学生要学习哦

强。。。。。。。。。。。。。。。。。。

千斤顶

xuexuexuexue

顶一下啊 

xuexile!!!!!!!!!!!!

haohaoahao 

谢谢楼主了,先顶一下

非常经典的文章

好东西需要学习学习啊

学习学习学习学习

顶一下

我初学者呀,这难度太大了,不懂呀

学习.刚开始用SQL2005

看上去  真的不错 学习

PAGE: (1:1504) -------------- BUFFER: ------- BUF @0x1912E300 --------------- bpage = 0x1A0D8000        bhash = 0x00000000        bpageno = (1:1504) bdbid = 18                breferences = 1           bstat = 0x9 bspin = 0                 bnext = 0x00000000         PAGE HEADER: ------------ Page @0x1A0D8000 ---------------- m_pageId = (1:1504)       m_headerVersion = 1       m_type = 1 m_typeFlagBits = 0x0      m_level = 0               m_flagBits = 0x8000 m_objId = 766742630       m_indexId = 0             m_prevPage = (0:0) m_nextPage = (0:0)        pminlen = 26              m_slotCnt = 2 m_freeCnt = 8002          m_freeData = 186          m_reservedCnt = 0 m_lsn = (58146:393:2)     m_xactReserved = 0        m_xdesId = (0:0) m_ghostRecCnt = 0         m_tornBits = 1             Allocation Status ----------------- GAM (1:2) = ALLOCATED     SGAM (1:3) = ALLOCATED     PFS (1:1) = 0x61 MIXED_EXT ALLOCATED  50_PCT_FULL   DIFF (1:6) = CHANGED ML (1:7) = NOT MIN_LOGGED  DATA: ----- Slot 0, Offset 0x60 ------------------- Record Type = PRIMARY_RECORD                         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS    1a0d8060:  001a0030  00000001  00000000  00009d3a 0...........:... 1a0d8070:  20333231  20202020  00052020  26000200 123       .....& 1a0d8080:  41002c00  00614342  00630062           .,.ABCa.b.c. Slot 1, Offset 0x8c ------------------- Record Type = PRIMARY_RECORD                         Record Attributes =  NULL_BITMAP VARIABLE_COLUMNS    1a0d808c:  001a0030  00000002  01530e45  00009d3c 0.......E.S.<... 1a0d809c:  37363534  20202020  00052020  26000200 4567      .....& 1a0d80ac:  44002e00  00644645  00660065      0067 ...DEFd.e.f.g. OFFSET TABLE: ------------- Row - Offset               1 (0x1) - 140 (0x8c)       0 (0x0) - 96 (0x60)        DBCC 执行完毕。如果 DBCC 输出了错误信息,请与系统管理员联系。 我把2000的DBCC PAGE 贴一下,以便参考,只是读取的方式不同而已,对换字节,偏移量没有对换

学习!!看看!

标注下。。。。。

引用 64 楼 sql77 的回复:SQL code PAGE: (1:1504) -------------- BUFFER: ------- BUF @0x1912E300 --------------- bpage = 0x1A0D8000        bhash = 0x00000000        bpageno = (1:1504) bdbid = 18                br…… 学习下 

强 不错

还得呀

我好累啊 论文不会写啊

太强了吧。

引用 72 楼 playwarcraft 的回复:

学习 谢谢

谢谢,前辈

ding

wo ding ding

Mark,收藏

xue xi le

真是高深啊!

学习了~~谢谢

谢谢分享

学习了。。。

学习了

努力学习中,还不太看的懂!

zhuang fen...........

来学习学习

学习..............

非常值得学习,顶一下

gaole

支持一个!!!~~~~~~~~~~~~~~

学习来的

想看懂 还真需要一段时间耶

学习 

努力学习中

虽说一直在用sql2000,还真不知道,学习了

更多的存储结构,请看: http://blog.csdn.net/downmoon/category/647266.aspx/rss

忽然想来连坐了。。

引用 98 楼 feixianxxx 的回复:忽然想来连坐了。。 .....

sf


上一篇:急聘兼职网络信息回复员! 40fredrickhu]
下一篇:数据库日志中发现有时帐号登录不了,但大多数情况下可以用,请问这是什么原因 40wch03521]

相关文章

相关评论

本站评论功能暂时取消,后续此功能例行通知。

一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!

二、互相尊重,对自己的言论和行为负责。

好贷网好贷款