SQL Server :理解数据记录结构
在SQL Server :理解数据页结构我们提到每条记录都有7 bytes的系统行开销,那这个7 bytes行开销到底是一个什么样的结构,我们一起来看下。
数据记录存储我们具体的数据,换句话说,它存在堆表里,或者存在聚集索引的叶子节点。数据记录结构是为了让SQL Server更高效的管理数据。我们来看下数据记录结构示意图:
上图中蓝色部分是所有数据记录部分(即系统行开销,大小基于列个数,等于或大于7 bytes),绿色部分是表结构里取决于定长/变长列的数据记录部分(实际存放的数据,大小基于实际数据)。
行头系统数据:
用做状态位1的第1字节(8位)是用来定义记录的属性:
- 第0位:版本信息,在SQL Server 2008里始终是0;
- 第1-3位:这3位用来定义记录类型;
- 0 数据记录(data record)
- 1 转发记录(Forwarded record)
- 2 转发存根(a forwarding stub)
- 3 索引记录(Index record)
- 4 二进制堆碎片或行溢出数据(blob fragment or row overflow data)
- 5 鬼影索引记录(ghost index record)
- 6 鬼影数据记录(ghost data record)
- 7 鬼影版本记录(ghost version record)
- 第4位:存在空值位图(Null bitmap )或没有。在SQL Server 2008里没有不为空的列也会有空值位图(Null bitmap );
- 第5位:表示是否存在变长列;
- 第6位:表示该列包含版本信息;
- 第7位:在SQL Server里未使用;
用作状态位2的第2字节(8位)。只有1位用来表示这条记录是否为鬼影转发记录(ghost forwarded record)。
由行头开始到定长列结尾长度:
下2个字节用来存储行头开始到定长列结尾长度。它包含2个状态位,2个字节用作这个列表示在表中定长数据的实际长度。例如如果表里没有定长列,这个列的值会是4。这和页头列pminlen显示的值是一样的。
所有定长列字段值(Fixed_Data_Size):
下n个字节用来存储在表中的定长数据,n就是在表中所有定长列的长度。如果表里的所有列都是变长列,这一部分就没有。
空值位图(Null_Bitmap):
下2个字节用来存储表里的列数。
下n个字节用作空值位图,每个bit对应一个列,1表示对应列为空。n的值为:列数 / 8,将值取整。
Variable_Data_Size:
下2个字节用来存储表里变长列个数。
下n个字节用来存储每个变长列结束为止的偏移量。每个变长列需要2字节,n的值为:变长列数 * 2 。
最后n个字节用来存储所有变长列值,n的值为所有变长列的实际长度的总长度。
我们来看一个具体的例子:
创建数据库,并插入2条记录
USE [InternalStorageFormat]
GO IF EXISTS ( SELECT *
FROM sysobjects
WHERE id = OBJECT_ID(N'[dbo].[Customers]')
AND OBJECTPROPERTY(id, N'IsUserTable') = 1 )
DROP TABLE dbo.Customers CREATE TABLE Customers
(
FirstName CHAR(50) NOT NULL,
LastName CHAR(50) NOT NULL,
Address CHAR(100) NOT NULL,
ZipCode CHAR(5) NOT NULL,
Rating INT NOT NULL,
ModifiedDate DATETIME NOT NULL,
)
GO INSERT INTO dbo.Customers
( FirstName ,
LastName ,
Address ,
ZipCode ,
Rating ,
ModifiedDate
)
VALUES ( 'Woody' , -- FirstName - char(50)
'Tu' , -- LastName - char(50)
'ZUOQIAO YOUXI TOWN LINHAI CITY' , -- Address - char(50)
'' , -- ZipCode - char(5)
1 , -- Rating - int
'2015-05-07 10:09:51' -- ModifiedDate - datetime
)
go 2
使用DBCC IND命令查看表对应页列表:
DBCC IND('InternalStorageFormat','Customers',-1)
我们看到数据页号为79。
使用DBCC PAGE命令查看页信息:
DBCC TRACEON(3604)
DBCC PAGE(InternalStorageFormat,1,79,3)
GO
在页头pminlen的值是221,包括定长列的总长217 bytes(50+50+100+5+4+8),2 bytes用作状态位(行头系统开销),2 byte 用作由行头开始到定长列结尾长度。
在记录槽提到的长度224,包括页头pminlen的值,1 byte用作空值位图(6/8 取整为1)和2 bytes 的字段个数。
我们来看一个变长列的表。
创建表并插入数据后,查看表对应的页:
CREATE TABLE VariableLength(
Title CHAR(10) NOT NULL,
FirstName VARCHAR(100),
Lastname VARCHAR(100),
email VARCHAR(50),
dob date NOT NULL,
phone CHAR(10),
Countrycode CHAR(3),
Designation VARCHAR(100),
PersonalPreference VARCHAR(100)
)
GO
INSERT INTO VariableLength VALUES ('Mr','Woody','Tu','smartgz@qq.com','2015-5-7','XXXXXXXXXX','Chn','DBA','Nothing Spl')
GO
DBCC IND('InternalStorageFormat','VariableLength',-1)
我们看到数据页号为202。
使用DBCC PAGE命令查看页信息:
DBCC TRACEON(3604)
GO
DBCC PAGE('InternalStorageFormat',1,202,3)--记得根据你的实际数据库,修改页号202
pminlen值为30,包含:
- 1 byte 状态位1
- 1 byte 状态为2
- 2 bytes 存储行头开始到定长列结尾长度
- 26 bytes 所有定长列总长度(10+3+10+3:tittle,dob,phone,countrycode)
Title CHAR(10) NOT NULL
dob date NOT NULL
phone CHAR(10)
Countrycode CHAR(3)
可以用下列语句验证下定长列总长度:
SELECT DATALENGTH(Title) title,DATALENGTH(dob) dob,DATALENGTH(phone) phone,DATALENGTH(Countrycode) countrycode FROM VariableLength
在槽0显示的81长度包含:
- 1 byte 状态位1
- 1 byte 状态为2
- 2 bytes 存储行头开始到定长列结尾长度
- 26 bytes 所有定长列总长度(10+3+10+3:tittle,dob,phone,countrycode)
Title CHAR(10) NOT NULL
dob date NOT NULL
phone CHAR(10)
Countrycode CHAR(3)
- 2 bytes 存储列个数
- 2 bytes 用作空值位图,字段个数/8后取整,即 9/8 得到2
- 2 bytes 存储变长列个数
- 10 bytes 用来存储每个变长列结束位置的偏移量 变长列个数 * 2,即 5 * 2 得到10,5个变长列包含:
FirstName VARCHAR(100)
Lastname VARCHAR(100)
email VARCHAR(50)
Designation VARCHAR(100)
PersonalPreference VARCHAR(100)
- 35 bytes 用来存储所有变长列的实际长度,这个可以使用下列语句得到
SELECT DATALENGTH(FirstName)+DATALENGTH(Lastname)+DATALENGTH(email)+
DATALENGTH(Designation)+DATALENGTH(PersonalPreference) FROM VariableLength
总结下每条记录的系统行开销:
行头系统数据(2 bytes)+由行头开始到定长列结尾长度(2 bytes)+列个数(2 bytes)+空值位图数据(取整(列个数/8) n bytes)
即 2 bytes + 2 bytes + 2 bytes + 取整(列个数/8)
当列个数小于等于8时,系统行开销始终是7 bytes,往上没增加8列,增加1 bytes,即系统系统行开销始终大于等于7 bytes。
对于在SQL Server里数据记录的存储格式,希望你已经有了清晰的认识。
SQL Server :理解数据记录结构的更多相关文章
- SQL Server 存储(2/8):理解数据记录结构
在SQL Server :理解数据页结构我们提到每条记录都有7 bytes的系统行开销,那这个7 bytes行开销到底是一个什么样的结构,我们一起来看下. 数据记录存储我们具体的数据,换句话说,它存在 ...
- SQL Server 存储(1/8):理解数据页结构
我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或写入所有数据页.页有不同的类型,像数据页,GA ...
- SQL Server :理解数据页结构
原文:SQL Server :理解数据页结构 我们都很清楚SQL Server用8KB 的页来存储数据,并且在SQL Server里磁盘 I/O 操作在页级执行.也就是说,SQL Server 读取或 ...
- Sql Server删除数据表中重复记录 三种方法
本文介绍了Sql Server数据库中删除数据表中重复记录的方法. [项目]数据库中users表,包含u_name,u_pwd两个字段,其中u_name存在重复项,现在要实现把重复的项删除![分析]1 ...
- SQL Server 变更数据捕获(CDC)监控表数据
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 实现过程(Realization) 补充说明(Addon) 参考文献(References) ...
- SQL Server大量数据秒级插入/新增/删除
原文:SQL Server大量数据秒级插入/新增/删除 1.快速保存,该方法有四个参数,第一个参数为数据库连接,第二个参数为需要保存的DataTable,该参数的TableName属性需要设置为数据库 ...
- 数据库迁移(SQL SERVER导入数据到MySql)
地址:http://blog.csdn.net/jiaohougenyang/article/details/44937801 背景:项目最开始时使用的是SQL Server数据库,业务需求现要将数据 ...
- 不同版本的SQL Server之间数据导出导入的方法及性能比较
原文:不同版本的SQL Server之间数据导出导入的方法及性能比较 工作中有段时间常常涉及到不同版本的数据库间导出导入数据的问题,索性整理一下,并简单比较下性能,有所遗漏的方法也欢迎讨论.补充. 0 ...
- 09Microsoft SQL Server 表数据插入,更新,删除
Microsoft SQL Server 表数据插入,更新,删除 向表中插入数据 INSERT INTO insert into tb1 values(0004,'张凤凤') insert into ...
随机推荐
- perl 异步超时 打印错误
#!/usr/bin/perl use AnyEvent; use AnyEvent::HTTP; my $cv = AnyEvent->condvar; sub doit{ my $url = ...
- 低头看—SQL视频
迷迷糊糊半个月过去了,耿大姐的数据库视频也在一知半解中看完.虽然耿大妈讲的很详细,很细心,但是我还是时不时的犯困(还不如看儿童英语动画片有精神呢)视频看是看完了,但东西不是自己的.这个时候就需要“颗粒 ...
- Swift - 炫酷放射弹出按钮菜单(改造自AwesomeMenu)
这个是一个第三方按钮菜单组件,原版是使用Objective-C编写的名为AwesomeMenu的组件,地址是:https://github.com/levey/AwesomeMenu 这里改造成了Sw ...
- Swift - 多行文本输入框(UITextView)的用法
1,多行文本控件的创建 1 2 3 4 var textview=UITextView(frame:CGRectMake(10,100,200,100)) textview.layer.borderW ...
- jsonp与cors跨域的一些理解(转)
CORS其实出现时间不短了,它在维基百科上的定义是:跨域资源共享(CORS )是一种网络浏览器的技术规范,它为Web服务器定义了一种方式,允许网页从不同的域访问其资源.而这种访问是被同源策略所禁止的. ...
- GCC编译优化指南【作者:金步国】
GCC编译优化指南[作者:金步国] GCC编译优化指南 作者:金步国 版权声明 本文作者是一位自由软件爱好者,所以本文虽然不是软件,但是本着 GPL 的精神发布.任何人都可以自由使用.转载.复制和再分 ...
- RAC 备份到本地不同设备
- cocos2d-x 3.0 使用最新物理引擎的一个源代码实例
1.碰撞函数參数由两个变成一个了 2.检測不到碰撞.须要设置那三个參数.同一时候还要设置成动态的. body进行设置. 3.初始入口文件也发生了改变. 附录上我近期调试好的cocos2d-x 3.1 ...
- ACM-简单题之Factorial——poj1401
转载请注明出处:http://blog.csdn.net/lttree Factorial Time Limit: 1500MS Memory Limit: 65536K Total Submis ...
- [项目整理]Win32,MFC的可执行文件只能运行一次
//第一种方法:控制release版本的exe文件只能运行一次 #ifndef _DEBUG //debug 版本中,项目属性-->预处理器 -->预处理定义: 有_DEBUG if (F ...