标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆/聚集索引

概述

最近要分享一个课件就重新把这块知识整理了一遍出来,篇幅有点长,想要理解的透彻还是要上机实践。

聚集索引

--创建测试数据库
CREATE DATABASE Ixdata
GO
USE [Ixdata]
GO
---创建测试表
CREATE TABLE Orders
(ID INT PRIMARY KEY IDENTITY(1,1),
NAME CHAR(80)NOT NULL,
IDATE DATETIME NOT NULL DEFAULT(GETDATE())
);
GO
---插入1000条测试数据
DECLARE @ID INT=1
WHILE(@ID<=1000)
BEGIN
INSERT INTO Orders(NAME)VALUES('商品'+CONVERT(NVARCHAR(20),@ID))
SET @ID=@ID+1
END
GO
SELECT * FROM Orders
GO

分析新创建的表的页的信息

---显示跟踪标志的状态
DBCC TRACESTATUS ---开启跟踪标志
DBCC TRACEON(3604,2588)
--DBCC TRACEOFF(3604,2588)
---获取对象的数据页,结构:数据库、对象、显示
DBCC IND(Ixdata,Orders,-1)

/*
1:显示所有分页的信息,包括IAM分页,数据分页,所有存在的LOB分页和行溢出页,索引分页
-1: 显示所有IAM、数据分页、及指定对象上全部索引的索引分页.
-2: 显示指定对象的所有IAM分页
0:显示所有IAM、数据分页.
*/

DBCC IND的表结构

还可以通过另一种方法来测试:

SELECT DISTINCT so.name, so.object_id,i.name AS index_name,sp.index_id,internals.type_desc,internals.total_pages, internals.used_pages, internals.data_pages,first_iam_page,  first_page, root_page
FROM sys.objects so
INNER JOIN sys.partitions sp ON so.object_id = sp.object_id
INNER JOIN sys.allocation_units sa ON sa.container_id = sp.hobt_id
INNER JOIN sys.system_internals_allocation_units internals ON internals.container_id = sa.container_id
LEFT JOIN sys.indexes i ON so.object_id=i.object_id AND sp.index_id=i.index_id
WHERE so.object_id = object_id('orders')

最后三个字段分别是IAM页,根页,和第一个数据页;它们分别用16进制来表示,拿first_iam_page来分析,首先将编码从右往左一个字节接着一个字节反过来排行(0X代表16进制),结果就是0X,00 01,00 00 00 50;前两个字节代表文件组号,最后4个字节代表页号。16进制的0001转换成10进制就是1;16进制的00 00 00 50转换成10进制就是5*16的1次方=5*16=80,所以第一个数据页是4*16+15=79,根页是5*16+9=89 结果和前面的查询出来的结果是一样的。从表格的otal_pages,used_pages,data_pages得到的结果也和前面查询出来的结果是一致的,总分配了17个页,使用了15个页包括13个数据页+1个IAM页+1个索引页。

手绘一张当前表格的聚集索引体系结构图:

分析索引页

---DBCC page的格式为(数据库,文件id,页号,显示)
DBCC page(Ixdata,1,89,3)

分析结果89页下面的子页总共有13页,每页80条记录,89索引页记录了每页的的键值的最小值,第一页就是id为1-80,第二页81-160,所以当你要找ID为150的数据的时候直接就可以去第90页里面找了。

PAGE HEADER

分析数据页

通过这些数据我们基本上可以知道90页的基本情况了,包括它的字段长度,上一页、下一页,还有该页的所以记录(这里没有截图出来).

插入20万条记录分析索引结构 

--插入20万条记录分析索引结构
DECLARE @ID INT=1
WHILE(@ID<=200000)
BEGIN
INSERT INTO Orders(NAME)VALUES('商品'+CONVERT(NVARCHAR(20),@ID))
SET @ID=@ID+1
END CREATE TABLE Page
(
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
);
GO
INSERT INTO Page EXEC('DBCC IND(Ixdata,Orders,-1)') ---查询索引页
SELECT [PageFID]
,[PagePID]
,[IAMFID]
,[IAMPID]
,[ObjectID]
,[IndexID]
,[PartitionNumber]
,[PartitionID]
,[iam_chain_type]
,[PageType]
,[IndexLevel]
,[NextPageFID]
,[NextPagePID]
,[PrevPageFID]
,[PrevPagePID]
FROM [Ixdata].[dbo].[Page]
WHERE PageType=2
go
select so.name, so.object_id, sp.index_id, internals.total_pages, internals.used_pages, internals.data_pages,first_iam_page,
first_page, root_page
from sys.objects so
inner join sys.partitions sp on so.object_id = sp.object_id
inner join sys.allocation_units sa on sa.container_id = sp.hobt_id
inner join sys.system_internals_allocation_units internals on internals.container_id = sa.container_id
where so.object_id = object_id('orders')

通过两种方法查询到的索引页的数量是一样的,下面的这种计算方法是2524-2513-1(IAM页)=10,其中807页是root_page页它在第二级,其它的是中间级索引页页就是第一级;页可以通过下面的16进制计算出来,IAM=5*16=80,ROOT_PAGE=3*16*16+2*16+7=807

再分析89页

---DBCC page的格式为(数据库,文件id,页号,显示)
DBCC page(Ixdata,1,89,3)

查询结果总共有269行,页就是269个数据页,orders表总共插入了201000条记录,一个页面存80条记录,就需要2513个页面和上面查询到的data_page是一样的。每个索引页存储269个数据页面就需要(‘select 2513*1.0/269’除不尽加1)10个索引页,查询最后一个索引页2698发现它还没分页共存储了361条记录,总共8*269+361=2513

手绘存储结构 

手绘的有点难看,但是意思差不多表达出来了。

大型对象 (LOB) 列

根据聚集索引中的数据类型,每个聚集索引结构将有一个或多个分配单元,将在这些单元中存储和管理特定分区的相关数据。每个聚集索引的每个分区中至少有一个 IN_ROW_DATA 分配单元。如果聚集索引包含大型对象 (LOB) 列,则它的每个分区中还会有一个 LOB_DATA 分配单元。如果聚集索引包含的变量长度列超过 8,060 字节的行大小限制,则它的每个分区中还会有一个 ROW_OVERFLOW_DATA 分配单元。

---创建测试表
CREATE TABLE Orderslob
(ID INT PRIMARY KEY IDENTITY(1,1),
NAME CHAR(80)NOT NULL,
Product NVARCHAR(MAX) NOT NULL,
IDATE DATETIME NOT NULL DEFAULT(GETDATE())
);
GO
---插入1000条测试数据
DECLARE @ID INT=1
WHILE(@ID<=1000)
BEGIN
INSERT INTO Orderslob(NAME,Product)VALUES(CONVERT(NVARCHAR(20),@ID)+'商品',REPLICATE(@ID,2))
SET @ID=@ID+1
END
--REPLICATE(@ID,200)
GO DBCC IND(Ixdata,Orderslob,1)

--查看2719数据页的信息
DBCC page(Ixdata,1,2719,1)

结果记录了每一条记录的偏移量。

每个人在自己的电脑上面测试页面id会不一样,但是反应的结果是一样的。

总结

本来想全部写完的,等写完这部分的时候发现篇幅已经有点长了,而且自己也有的吃不消熬到1点才写完,接下来还有中下两部分会尽快在几天内写完,欢迎关注。

备注:

作者:pursuer.chen

博客:http://www.cnblogs.com/chenmh

本站点所有随笔都是原创,欢迎大家转载;但转载时必须注明文章来源,且在文章开头明显处给明链接,否则保留追究责任的权利。

《欢迎交流讨论》

SQL Server 深入解析索引存储(上)的更多相关文章

  1. SQL Server 深入解析索引存储(下)

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/非聚集索引 概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非 ...

  2. SQL Server 深入解析索引存储(非聚集索引)

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/非聚集索引 概述 非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非 ...

  3. SQL Server 深入解析索引存储(中)

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆 概述 本篇文章是关于堆的存储结构.堆是不含聚集索引的表(所以只有非聚集索引的表也是堆).堆的 sys.parti ...

  4. SQL Server 深入解析索引存储(堆)

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆 概述 本篇文章是关于堆的存储结构.堆是不含聚集索引的表(所以只有非聚集索引的表也是堆).堆的 sys.parti ...

  5. SQL Server 深入解析索引存储(聚集索引)

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/索引体系结构/堆/聚集索引 概述 最近要分享一个课件就重新把这块知识整理了一遍出来,篇幅有点长,想要理解的透彻还是要上机实践. 聚 ...

  6. SQL Server 表和索引存储结构

    在上一篇文章中,我们介绍了SQL Server数据文件的页面类型,系统通过96个字节的头部信息和系统表从逻辑层面上将表的存储结构管理起来,具体到表的存储结构上,SQL Server引入对象.分区.堆或 ...

  7. SQL SERVER全面优化-------索引有多重要?

    想了好久索引的重要性应该怎么写?讲原理结构?我估计大部分人不愿意看,也不愿意花那么多时间仔细研究.光写应用?感觉不明白原理一样不会用.举例说明?情况太多也写不全....到底该怎么写呢? 随便写吧,想到 ...

  8. SQL Server 堆表行存储大小(Record Size)

    一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 堆表行记录存储格式(Heap) 案例分析(Case) 参考文献(References) 二.背 ...

  9. Sql Server系列:索引基础

    1 索引概念 索引用于快速查找在某个列中某个特定值的行,不使用索引,数据库必须从第1条记录开始读完整个表,知道找出需要的行.表越大,查询数据所花费的时间越多.如果表中查询的列有索引,数据库能快速到达一 ...

随机推荐

  1. SGIP、SMGP 长短信发送问题小结

    长短信发送问题.1.将信息长度拆开发送.2.为了解决长短信拆分发送,在手机终端,收到的顺序错乱,所以在每一段短信发送完成后,延时5秒,这样在手机终端客户收到的信息,就会按照拆分的顺序发送. //信息总 ...

  2. 域名解析服务查询工具dnstracer

    域名解析服务查询工具dnstracer   在访问网站过程中,当用户输入网址后,通常是先解析域名,获取该网站的IP地址.然后,根据IP地址访问对应的网站服务器.所以,域名解析服务器保证域名指向正确的网 ...

  3. 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...

  4. PHP CI框架 result()详解

    该方法执行成功返回一个对象数组,失败则返回一个空数组. 一般情况下,我们使用下面的方法遍历结果,代码就像这样: $query = $this->db->query("要执行的 S ...

  5. my links

    如何解決MySQL 開動不到的問題 MySQL start fail 10 BEST JQUERY FILE UPLOAD PLUGINS WITH IMAGE PREVIEWS Spring MVC ...

  6. 如何在Web引用中使用项目自定义的类

    这个是老架构了,不推荐现在这么用,维护一个老项目记录一下. 项目中WebService和客户端是在一个解决方案下,实体类是一个公用的Project,如果使用Web引用自动生成的类会缺少一些实体类定义的 ...

  7. 利用PHP的ob函数实现生成静态化页面

    之前用过一些开源的CMS管理系统,当时就很好奇后台中的生成HTML静态文件是怎么实现的.今天和同事讨论了下,没想到同事之前做过这类的生成静态页面的功能,果断向他请教了下. 经他讲解后,才知道其实生成静 ...

  8. 经典排序算法 – 插入排序Insertion sort

    经典排序算法 – 插入排序Insertion sort  插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕. 插入排序方法分直接插入排序和折半插入排序两种, ...

  9. 转行|如何成为企业想要的Android工程师

    没经验 一来没钱 二来没时间 三来投简历没人要 四来就算忽悠进去了,也做不了,亚历山大,迟早被踢 1.做好手上的工作 不要裸辞 忌讳心猿意马的心态,当有两个选择的时候,往往 所以要专注于当下手头上唯一 ...

  10. MAC帧和IP数据报