深入剖析行溢出的存储结构-阿里云开发者社区

开发者社区> 努力酱> 正文

深入剖析行溢出的存储结构

简介:
+关注继续查看
20151223101035504.jpg
 

 

 

目录

 

  • 什么时候触发行溢出

  • 行溢出的存储结构

  • 行溢出的整体逻辑结构图

  • 总结

 

 

本文以SQL Server为例聊聊行溢出的存储结构

 

1什么时候触发行溢出

SQL Server的行溢出数据只会发生在变长字段上,变长列的长度不能超过标准变长列最大值8000个字节的限制,而且还要满足:

 

  • 包括行头系统信息和所有定长列和变长系统信息的所有长度不能超过8060字节,要想存储8000字节以上的数据,应该使用LOB(text、ntext或者image)或者MAX数据类型;

  • 变长列的实际长度一定要超过24个字节(因为行溢出需要额外的24个字节行溢出指针,如果变长字段值不超过24个字节,完全没有必要把它作为行溢出数据存储);

  • 变长列不能是聚集索引键的一部分(如果行溢出是聚集索引键的一部分,那么表的查询性能会是一个噩梦);

2行溢出的存储结构

为了了解Overflow的结构,我们创建表HeapPage_Overflow,并插入测试数据:

 

20160801054429171.png

 

查看这行记录对于Page的内容:

20160801054437749.png


上面Page数据中的一行记录可以格式化为下图所示:

20160801054457328.jpg

图1:堆表HeapPage_Overflow记录结构

 

其中几个重要部分结构解释如下:

 

  • 0x2980这是包含后面指向存储行溢出的变长字段偏移量。把0x2980逆序成0x8029,再把0x8029转换为二进制1000000000101001,去除高2位(也就是粗体部分),取101001,转换为十进制就是41,高2位的目的其实只是一个标识,为了跟普通记录的变长字段偏移量进行区分。

 

  • 第一个变长字段偏移量41是由17个字节系统信息加上24个字节的行溢出指针共同组成,计算公式为:41=17+24,下面对这24个字节的行溢出指针进行结构分析:

 

 

20160801054514386.jpg

图2:堆表HeapPage_Overflow的行溢出指针结构

 

 

  • 0x02,特殊字段的类型,0x02表示行溢出数据;

  • 0x0000,表示B树中的层级,行溢出的记录,这个值为始终为0,在LOB记录的ROOT记录中这个值为0x0100;

  • 0x00,暂时未使用;

  • 0x01000000,一个序列号,每次行溢出或LOB数据被更新时这个值加1,并在乐观并发控制为游标使用;

  • 0x804A0000,Timestamp值,用于使用DBCC CHECKTABLE检查表索引、行内、LOB 以及行溢出数据页是否已正确链接。在LOB的行内数据、LOB的ROOT指针以及存储LOB的数据结构中都存储了这个值,而且他们的值都是一样的。0x804A0000逆序之后是0x0004A80,再向0x0004A80后面追加4个0得到0x0004A800000,转换为十进制为1249902592;要验证这个标识值的算法,可以使用工具Winhex修改0x804A0000值并使用DBCC PAGE(Overflow,1,93,3) 查看Timestamp值。

  • 0x70170000,溢出字段长度,0x70170000逆序之后是0x00001770,用十进制表示是6000,这个跟前面插入记录时字段的大小完全吻合;

  • 0x5900000001000000表示一个8个字节的RID地址,指向行溢出字段VarCol存储6000字节所在数据页的RID地址为:(1:89:0)。

 

上面已经分析了在行内数据中存储的行溢出指针的结构,接下来将分析存储行溢出数据的物理结构。

 

查看行溢出存储Page的内容:
20160801054534668.png

 

上面Page数据中的一行记录可以格式化为下图所示:

20160801054559503.jpg

图3:堆表HeapPage_Overflow的行溢出数据结构

 

  • 0x0800是这一行记录的行头数据,分解为Byte#0的十六进制是0x08和Byte#1的十六进制是0x00,0x08转换为二进制是:00001000,各个bit表示的含义如下:

 

20160801054609923.jpg

图4:堆表HeapPage_Overflow的行溢出行头结构

 

 

  • 0x7E17是变长偏移量,经过逆序之后是0x177E,用十进制表示是6014,这个偏移量包含了14个字节的行溢出系统数据和6000个字节的行溢出字段值;

  • 0x0000804A00000000是Blob Id值,跟IN_ROW_DATA记录中24个字节的行溢出指针的Timestamp值是相等的。要验证这个标识值的算法,可以使用工具Winhex修改0x0000804A00000000的值并使用DBCC PAGE(Overflow,1,89,3)查看这个Blob Id值。如果不相等,虽然SELECT一样能查询数据,但是在进行DBCC CHECKDB将会报引用不匹配的错误信息。

  • 0x0300是数据类型,转换为十进制是3,Type=3表示DATA,即表示这行记录是用于存储数据的。

3行溢出的整体逻辑结构图

根据上面对行记录存储结构的分析,行溢出的逻辑可以通过下面的图来表示:

 

20160801054635362.jpg

图5:堆表HeapPage_Forward第一行记录行溢出后的存储结构示意图

4总结

上文以堆表的行溢出数据为例讲解它的存储结构,从结构来看一行记录的存储跨越了两个Page,相比于一条记录存储在一个Page里,查询的时候增加了1个IO,当表比较大的时候,随机IO将会猛增,将会出现性能上的问题,一般建议控制好变长字段的大小,或者使用其它数据类型避免行溢出,也可以考虑表的垂直拆分。

更多关于SQL Server存储结构请参考《SQL Server性能调优实战》

 

 

作者介绍:陈畅亮

 

  • 【DBA+社群】广州联合发起人

  • 微软SQL Server方向最有价值专家(MVP),《SQL Server性能调优实战》作者,《Windows PowerShell实战指南(第2版)》译者。

  • 主要研究MySQL、SQL Server、NoSQL,以及分布式环境下海量数据存储的设计与开发。

  • 2015年DTCC大会演讲嘉宾


本文来自云栖社区合作伙伴"DBAplus",原文发布时间:2015-12-23

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
8系列TEE-Lite异常中断向量表和服务程序的存储结构
本文介绍 8系列TEE-Lite异常中断向量表和服务程序的存储结构
257 0
数据结构与算法——图论基础与图存储结构 | 算法必看系列三十一
图是数据结构中重要内容。相比于线性表与树,图的结构更为复杂。在线性表的存储结构中,数据直接按照前驱后继的线性组织形式排列。在树的结构中,数据节点以层的方式排列,节点与节点之间是一种层次关系。但是,在图的结构中数据之间可以有任意关系,这就使得图的数据结构相对复杂。
2227 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
3993 0
怎么设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程
6322 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
3950 0
图的存储结构的实现(C/C++实现)
存档: 1 #include 2 #include 3 #define maxv 10 4 #define max 10 5 typedef char elem; 6 typedef int elemtype; 7 #include "queue.
1055 0
8系列TEE-Lite异常中断向量表和服务程序的存储结构
本次介绍主要介绍和异常,中断相关的几种存储方式,在传统的处理器设计中,中断和异常是需要通过异常/中断向量表作为索引的,根据不同的应用场景会出现一张或者多张一场异常/中断向量表。
261 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
5660 0
零零散散学算法之详解几种数据存储结构
所谓数据存储结构,就是数据的元素与元素之间在计算机中的一种表示,它的目的是为了解决空间规模问题,或者是通过空间规模问题从而间接地解决时间规模问题。
635 0
[Linux 存储管理] LVM结构
linux的LVM灵活且功能强大,当然越强大的就越难理解。lvm和硬盘大致关系应该如下,如果有误请大家左证。 lvm中快照功能强大到,很多db的备份都依赖于这个功能,所以不能不理解和熟悉。 《鸟哥linux私房菜 基础学习篇》 15.3 逻辑卷管理器 中有LVM几个命令的实战应用
641 0
+关注
287
文章
3
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载