SQL Server 深入解析索引存储(中)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆
概述
本篇文章是关于堆的存储结构。堆是不含聚集索引的表(所以只有非聚集索引的表也是堆)。堆的 sys.partitions 中具有一行,对于堆使用的每个分区,都有 index_id = 0。默认情况下,一个堆有一个分区。当堆有多个分区时,每个分区有一个堆结构,其中包含该特定分区的数据。例如,如果一个堆有四个分区,则有四个堆结构;每个分区有一个堆结构。根据堆中的数据类型,每个堆结构将有一个或多个分配单元来存储和管理特定分区的数据。每个堆中的每个分区至少有一个 IN_ROW_DATA 分配单元。如果堆包含大型对象 (LOB) 列,则该堆的每个分区还将有一个 LOB_DATA 分配单元。如果堆包含超过 8,060 字节行大小限制的可变长度列,则该堆的每个分区还将有一个 ROW_OVERFLOW_DATA 分配单元。有关分配单元的详细信息,
sys.system_internals_allocation_units 系统视图中的列 first_iam_page 指向管理特定分区中堆的分配空间的一系列 IAM 页的第一页。SQL Server 使用 IAM 页在堆中移动。堆内的数据页和行没有任何特定的顺序,也不链接在一起。数据页之间唯一的逻辑连接是记录在 IAM 页内的信息。
正文
堆结构
可以通过扫描 IAM 页对堆进行表扫描或串行读操作来找到容纳该堆的页的扩展盘区。因为 IAM 按扩展盘区在数据文件内存在的顺序表示它们,所以这意味着串行堆扫描连续沿每个文件进行。使用 IAM 页设置扫描顺序还意味着堆中的行一般不按照插入的顺序返回。

页面的组成

一个SQL数据页面=标头+数据行+剩余空间+行偏移表(如果表中存在大数据类型字段)+溢出表(如果存在)
行偏移
---测试数据
CREATE TABLE Theap
(ID INT IDENTITY(1,1) NOT NULL,
NAME NVARCHAR(MAX) NOT NULL,
IDATE DATETIME DEFAULT(GETDATE()) NOT NULL
)
GO
---插入1000条测试数据
DECLARE @ID INT=1
WHILE(@ID<=1000)
BEGIN
INSERT INTO Theap(NAME)VALUES((@ID))
SET @ID=@ID+1
END
GO
SELECT * FROM Theap ---开启跟踪标志
DBCC TRACEON(3604,2588)
--DBCC TRACEOFF(3604,2588)
---获取对象的数据页,结构:数据库、对象、显示
DBCC IND(Ixdata,Theap,-1) SELECT * FROM sys.system_internals_allocation_units WHERE container_id=72057594039566336


分析114页
DBCC page(Ixdata,1,114,3)
整个数据页有四部分组成
1.页面在内存中的映射信息(BUFFER:)

2. 页头部分(PAGE HEADER):记录了页号、页类型、记录数,LSN及其他信息,在上一章已经讲过

3. 数据部分(DATA):以16进制格式存储行记录(从第96个字节开始)

4. 行偏移部分(OFFSET TABLE):以倒序的顺序记录了行记录的指针位置,这个使用2的显示方式比较明显看出

看看一行记录在页面中是怎样记录的



00000000: 30001000 01000000 76ff7401 64a40000 †0.......v.t.d...
00000010: 0300b801 00190031 00†††††††††††††††††.......1.
1字节:30>00110000 ;右边第一位开始是0位,第4位和第5位是1,由于在2008中null bit map总是存在的,所以只考虑第五位,即存在变长字段。
1字节:00;状态位B在SQLServer2005/2008中未启用,所以为00
2字节:1000;这两个字节是表示定长列的字节数,反过来排0010=1*16=16个字节,表中的定长列ID(4个字节)+IDATE(8个字节)+4个字节(默认加的)=16个字节
N个字节:01000000 76ff7401 64a40000;这N个字节是定长字段的内容,总共12个字节
2个字节:0300;表中的字段数,由于表中只有3个字段所以用0300表示
1个字节:b8>10111000;这个字节表示主要是判断对应的字段内容是否有空值,1代表允许为空,前三个字段都不允许为空,而且表只有三个字段所以不用看后面。
2个字节:01 00;这个字段表示变长列的个数,根据刚才说的方法倒过来00 01=1个字段,表中页只有NAME字段是变长字段。
2个字节*变长字段的个数:1900;由于表中只有一个变长字段,所以只有两个字节,表示第一个变长列的终止位置=25
N个字节:变长字段的内容,3100转换成字符刚好是‘1’
在线16进制转字符:http://www.bejson.com/tools/0x/
查询
SELECT [ID]
,[NAME]
,[IDATE]
FROM [Ixdata].[dbo].[Theap]
WHERE NAME='' SELECT [ID]
,[NAME]
,[IDATE]
FROM [Ixdata].[dbo].[Theap]
WHERE NAME=''


分析查询可以看出无论你查询的是'1'还是'900',都是扫描一次,逻辑读取4次,因为存在4个页,用ID去查也是一样.
行溢出
CREATE TABLE Theapover
(ID INT IDENTITY(1,1) NOT NULL,
NAME VARCHAR(5000) NOT NULL,
NAME1 VARCHAR(5000) NOT NULL,
IDATE DATETIME DEFAULT(GETDATE()) NOT NULL
)
GO
---插入1000条测试数据
DECLARE @ID INT=1
WHILE(@ID<=1000)
BEGIN
INSERT INTO Theapover(NAME,NAME1)VALUES(REPLICATE(1,5000),REPLICATE(2,5000))
SET @ID=@ID+1
END
GO
SELECT * FROM Theapover
ORDER BY ID
GO DBCC IND(Ixdata,Theapover,-1) SELECT * FROM sys.system_internals_allocation_units WHERE container_id=72057594039828480


总共插入了1000条记录,一行占一页再加上两个IAM页刚好2002页,
存在两个IAM页,分别是3281和3283页,还有一个比较特殊的页3280页,3280页是溢出数据里面的根页,等一下看一下这页的数据。
分析IAM页
DBCC page(Ixdata,1,3283,3)

分析溢出页
DBCC page(Ixdata,1,3282,3)


注意:不是堆页和溢出页就只能一一对应,由于当前表中堆页容纳不下两条记录所以就导致了堆页和溢出页一样,当堆页可以存多条记录的时候就会出现一个堆页对应多个溢出页。
测试查询
SELECT [ID]
,[NAME]
,[NAME1]
,[IDATE]
FROM [Ixdata].[dbo].[Theapover]
where ID=500

当我继续往堆表里插入数据直到表超过4G的时候会有新的IAM页生成,而且IAM页之间存在链关系(数据页)。

查询发现新生成的3135IAM页种的数据页的行溢出指向的是新生成的511256IAM页的溢出页,这样的话IAM页之间的链关系对查询效率貌似没有什么改善的好处。
1. IAM用于查找分配给heap的所有数据页信息,IAM页中记录了所有的页面的页id。
2. 对于大多数较小的heap表来说,仅需要一个IAM页就可以管理其页面。
3. 若heap表大于4GB或包含LOB数据类型的话,则会包含多个IAM页面。
4. 当查询要获取heap表的所有记录时,SQL Server使用IAM页来扫描heap表
总结
堆表的页是没有规律的不存在页链,所以导致堆表的查询效率很差,当查询一个10万条记录的堆表逻辑读取就需要10万次,如果堆表的数据量很大需要多次进行物理读获取页面的时候对于IO的消耗是非常大的,建议表都应该建聚集索引。
|
备注: 作者:pursuer.chen 博客:http://www.cnblogs.com/chenmh 本站点所有随笔都是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接,否则保留追究责任的权利。 《欢迎交流讨论》 |
SQL Server 深入解析索引存储(中)的更多相关文章
- SQL Server 深入解析索引存储(下)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/非聚集索引 概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非 ...
- SQL Server 深入解析索引存储(非聚集索引)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/非聚集索引 概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非 ...
- SQL Server 深入解析索引存储(上)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆/聚集索引 概述 最近要分享一个课件就重新把这块知识整理了一遍出来,篇幅有点长,想要理解的透彻还是要上机实践. 聚 ...
- SQL Server 深入解析索引存储(堆)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆 概述 本篇文章是关于堆的存储结构.堆是不含聚集索引的表(所以只有非聚集索引的表也是堆).堆的 sys.parti ...
- SQL Server 深入解析索引存储(聚集索引)
标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆/聚集索引 概述 最近要分享一个课件就重新把这块知识整理了一遍出来,篇幅有点长,想要理解的透彻还是要上机实践. 聚 ...
- SQL Server 表和索引存储结构
在上一篇文章中,我们介绍了SQL Server数据文件的页面类型,系统通过96个字节的头部信息和系统表从逻辑层面上将表的存储结构管理起来,具体到表的存储结构上,SQL Server引入对象.分区.堆或 ...
- SQL SERVER全面优化-------索引有多重要?
想了好久索引的重要性应该怎么写?讲原理结构?我估计大部分人不愿意看,也不愿意花那么多时间仔细研究.光写应用?感觉不明白原理一样不会用.举例说明?情况太多也写不全....到底该怎么写呢? 随便写吧,想到 ...
- SQL Server 堆表行存储大小(Record Size)
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 堆表行记录存储格式(Heap) 案例分析(Case) 参考文献(References) 二.背 ...
- SQL查询优化:详解SQL Server非聚集索引(转载)
本文是转载,原文地址 http://tech.it168.com/a2011/1228/1295/000001295176.shtml 在SQL SERVER中,非聚集索引其实可以看作是一个含有聚集索 ...
随机推荐
- 再谈缓存和Redis
自从上次分享<Redis到底该如何利用?>已经有1年多了,这1年经历了不少.从码了我们网站的第一行开始到现在,我们的缓存模块也不断在升级,这之中确实略有心得,最近也有朋友探讨缓存,觉得可以 ...
- C#运算符号
double x=5.1e3;// 5.1乘以10 的3次方. x就是 5100 //注 : 5.1e+3=5.1e3=5.1e03=5.1e+03 double y=5.1e-3;// 5.1乘以 ...
- Git使用笔记
Ubuntu下安装步骤 sudo apt-get install git完成git的安装 安装完成后进行配置 git config –global user.name “Your Name” git ...
- ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
有时候,当我们使用"mysql"."mysqladmin"."mysqldump"等命令管理数据库时,服务器抛出类似如下错误: 一.错误现场 ...
- APPCAN开发笔记:html页面之间的参数传递:使用js获取url中的参数,以及在APPCAN中不能使用的解决方法
用PHP的GET/POST方式来传递方式已经是司空见惯了,但是如果我的页面是一个静态的html的页面,想传递参数的时候要怎么办呢?在APPCAN的开发中我们会经常遇到这样的问题,因为所有的页面都是静态 ...
- 【Python装饰者】在函数测试的作用
[引言] 我们经常需要多函数进行耗时测试,测试方法有许多,这里介绍装饰者的方法,提高耗时测试代码的可复用性,在其他方面的应用也是如此. [设计原则] 类应该对扩展开放,对修改关闭. [代码] (1)定 ...
- java方法重载(overload)、重写(override);this、super关键简介
一.方法重载: 条件:必须在一个类中,方法名称相同,参数列表不同(包括:数据类型.顺序.个数),典型案例构 造方重载. 注意:与返回值无关 二.方法重写: 条件: (1)继承某个类或实现某接口 (2 ...
- install hdp 2.2 on ubuntu 14.04
http://www.swiss-scalability.com/2014/12/install-hdp-22-on-ubuntu-1404-trusty.html 在新加节点上运行 sed -e & ...
- BestCoder#51
#include <cstdio> #include <iostream> #include <cmath> #include <cstring> us ...
- 微软官方提供的免费正版 Windows 8.1/Win10/7/XP/Vista 操作系统虚拟机镜像下载
https://dev.windows.com/en-us/microsoft-edge/tools/vms/windows/