设为首页 收藏本站
查看: 1368|回复: 0

[经验分享] 《Microsoft Sql server 2008 Internals》读书笔记--第七章Special Storage(1)

[复制链接]

尚未签到

发表于 2015-7-1 07:57:05 | 显示全部楼层 |阅读模式
  
  《Microsoft Sql server 2008 Internals》读书笔记订阅地址:
  http://www.iyunv.com/downmoon/category/230397.html/rss
  《Microsoft Sql server 2008 Internals》索引目录:
  《Microsoft Sql server 2008 Internal》读书笔记--目录索引
  
  第五章《Table》和第六章《Indexes:Internals and Management》我们主要讨论了“规则行”在表和索引中的存储机制,第五章中我们了解到规则行是以“固定变量”的格式存储,SQL Server提供了另外一种格式存储数据,即“列描述”(Column Descriptor)。它能存储一些特殊的值(包括固定变量和不能适应常规8-KB大小页面的CD格式的值),在这章中。我们将讨论一些超过正常数据行 大小限制的数据,它们被存储作为"行溢出"或Large Object(LOB)数据。此外,SQL Server 2008还提供了一种常规列的复杂存储列,即稀疏列(Sparse Columns),和新的CD格式(compressed data)。另外,还将讨论文件流访问,即SQL Server访问操作系统的文件。最后将讨论SQL Server分离数据到分区的操作。
   ■Large Object Storage
  根据第五章的知识,我们了解到8k=8192字节中,只有8060字节是用于存储数据,如果一个表的行长度超过8060,将会收到一条提示:


USE testdb;
go
CREATE TABLE dbo.bigrows_fixed  
(   a char(3000),  
    b char(3000),
    c char(2000),
    d char(60) ) ;
--Msg 1701, Level 16, State 1, Line 2
--Creating or altering table 'bigrows_fixed' failed because the minimum row size would be 8067, including 7 bytes of internal overhead. This exceeds the maximum allowable table row size of 8060 bytes.
---- The following code creates a table with rows that have a maximum defined length that is much longe  
  
  你可以看到8067中有7个字节用于存储行自身的开销。其实还有两个字节用于存储行偏移,但没有包含在这7个字节,详见前文第五章部分。
   ■限制长度的大对象数据(行溢出数据Row-Overflow Data)
  超过8060字节的行限制的一个方法是使用可变长度列。因为SQL Server 2005/2008会使用“行溢出”页面来存储这些列,只要固定长度列不超过限制即可。可变长度列包括 varbonary,varchar,nvarchar,sqlvariant等,还可以是在CLR中用户定义的数据类型。
  如下语句:


CREATE TABLE dbo.bigrows  
  (a varchar(3000),  
   b varchar(3000),
   c varchar(3000),
   d varchar(3000) );   
  事实上。这个语句在SQL Server 7.0出错而不会被执行,SQL Server 2000中会执行,但会收到一个警告,超过8060的行可能会被截断。而在SQL Server 2005/2008中,你不但可以创建表,而且可以插入超过8060字节的数据。如下:


INSERT INTO dbo.bigrows
     SELECT REPLICATE('e', 2100), REPLICATE('f', 2100),
      REPLICATE('g', 2100),  REPLICATE('h', 2100);
--我们来确认一下SQL Server是如何存储行溢出数据的:
SELECT object_name(object_id) AS name,  
    partition_id, partition_number AS pnum,  rows,  
    allocation_unit_id AS au_id, type_desc as page_type_desc,
    total_pages AS pages
FROM sys.partitions p  JOIN sys.allocation_units a
   ON p.partition_id = a.container_id
WHERE object_id=object_id('dbo.bigrows');
--name    partition_id    pnum    rows    au_id    page_type_desc    pages
--bigrows    72057594043432960    1    1    72057594045005824    IN_ROW_DATA    2
--bigrows    72057594043432960    1    1    72057594045071360    ROW_OVERFLOW_DATA    2  结果中可以看出,这一行中有两个页用来存放规则“行内”数据,两个页来存放“行溢出”数据,此外,我们还可以使用DBCC IND命令来查看更详细的四个页的存储,
注意:当表开始增长时,这个命令将无法应付成千上万的页,第六章提供了一个sp_tablepages脚本,可以很方便捕获DBCC的输出。


INSERT INTO sp_tablepages
    EXEC ('DBCC IND (testdb, bigrows, -1)')
SELECT PageFID, PagePID, ObjectID, PartitionID, IAM_chain_type, PageType
FROM sp_tablepages; DSC0000.gif
DSC0001.gif
  在上图中,e(对应ascii码为65)与g(67)之间对应的部分前16个字节存储了Row-Overflow的指针,如下:
  
字节数十六进制值十进制值
Meaning
00x0221=LOB;2=Overflow
1-20x00000B树等级,对OverFlow始终为0
30x000未使用
4-70x00000163?序列号,在优化并发时使用
8-110x004ae100?时间戳
12-150x000008342100长度
  
  SQL Server 在一定条件下存储可变长度列在行溢出页。决定因素在于行自身的长度,即只有行自身需要超过8060字节时才会选择。表中的每一行要么全在行中,要么全在行 外。一个行如果包含多个large Variable-length列,那么它可以跨越多个行溢出页。  例如:


CREATE TABLE dbo.hugerows  
  (a varchar(3000),  
   b varchar(8000),
   c varchar(8000),
   d varchar(8000));

INSERT INTO dbo.hugerows
     SELECT REPLICATE('a', 3000), REPLICATE('b', 8000),
         REPLICATE('c', 8000),  REPLICATE('d', 8000);
--name    partition_id    pnum    rows    au_id    page_type_desc    pages
--hugerows    72057594043498496    1    1    72057594045136896    IN_ROW_DATA    2
--hugerows    72057594043498496    1    1    72057594045202432    ROW_OVERFLOW_DATA    4   注意:虽然SQL  Server提供了大容量数据存储方式,你可以高效的使用特殊数据存储而不必重新设计你的表结构,但是,最佳的使用环境是:表的大部分数据是在行内(即常规数据)而偶尔需要大容量数据处理。
  在某些情况下,如果一个大的可变长度列被收缩,可能变成常规列,然而,出于效率考虑,如果仅减少几个字节,SQL Server并不会检查是否需要改变。只有改变长度超过1000字节时,SQL Server才会检查是否需要移动为常规列。
  看前 面的例子,我们修改行的长度:


UPDATE bigrows
SET a = replicate('a', 1600);  行总长度减为7900,减少500字节,此时,你仍然可以看到两个row-flow 页

代码

--name    partition_id    pnum    rows    au_id    page_type_desc    pages
--bigrows    72057594043432960    1    1    72057594045005824    IN_ROW_DATA    2
--bigrows    72057594043432960    1    1    72057594045071360    ROW_OVERFLOW_DATA    2  再执行一次:


UPDATE bigrows
SET a = 'aaaaa';  
  注意:行溢出数据存储仅仅应用于可变长度列,即不超过8000字节的常规列,而且,存储可变长度列在行溢出页,你还必须下列条件:
  1、所有固定长度列,包括开销字节(overhaed bytes,还有24字节指针指向数据溢出页),总和加起来不超过8060字节。
  2、可变长度列的实际数据必须大于24字节。
  3、 该列必须不是聚集索引键的一部分。
  如果,单个列长度超过8000字节,则应使用LOB(text,image or ntext) 列或Max数据类型。
  本文简单介绍了限制长度的Large Object Data存储形式,下一节将介绍不限长度的Large Object Data存储形式。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-82082-1-1.html 上篇帖子: SQL Server 的Collate语句需注意 下篇帖子: 没有装Express版Sql Server 2005就不能用WebPart ?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表