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

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
云数据库 RDS SQL Server,基础系列 2核4GB
云解析 DNS,旗舰版 1个月
简介:
2015-03-25 09:12 by pursuer.chen, 1664 阅读, 1 评论, 收藏, 编辑

标签: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='1'
    
  SELECT [ID]
      ,[NAME]
      ,[IDATE]
  FROM [Ixdata].[dbo].[Theap]
  WHERE NAME='900'
复制代码

分析查询可以看出无论你查询的是'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/p/4359171.html,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
打赏
0
0
0
0
20
分享
相关文章
SQL优化策略与实践:组合索引与最左前缀原则详解
本文介绍了SQL优化的多种方式,包括优化查询语句(避免使用SELECT *、减少数据处理量)、使用索引(创建合适索引类型)、查询缓存、优化表结构、使用存储过程和触发器、批量处理以及分析和监控数据库性能。同时,文章详细讲解了组合索引的概念及其最左前缀原则,即MySQL从索引的最左列开始匹配条件,若跳过最左列,则索引失效。通过示例代码,展示了如何在实际场景中应用这些优化策略,以提高数据库查询效率和系统响应速度。
52 10
【YashanDB知识库】字段加上索引后,SQL查询不到结果
【YashanDB知识库】字段加上索引后,SQL查询不到结果
深入解析MySQL的EXPLAIN:指标详解与索引优化
MySQL 中的 `EXPLAIN` 语句用于分析和优化 SQL 查询,帮助你了解查询优化器的执行计划。本文详细介绍了 `EXPLAIN` 输出的各项指标,如 `id`、`select_type`、`table`、`type`、`key` 等,并提供了如何利用这些指标优化索引结构和 SQL 语句的具体方法。通过实战案例,展示了如何通过创建合适索引和调整查询语句来提升查询性能。
805 9
|
6月前
|
深入探索数据库索引技术:回表与索引下推解析
【10月更文挑战第15天】在数据库查询优化的领域中,回表和索引下推是两个核心概念,它们对于提高查询性能至关重要。本文将详细解释这两个术语,并探讨它们在数据库操作中的作用和影响。
119 3
|
2月前
|
【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
在 Flutter 开发中,AzListView 是实现字母索引分类列表的理想选择。它支持 A-Z 快速跳转、悬浮分组标题、自定义 UI 和高效性能,适用于通讯录、城市选择等场景。本文将详细解析 AzListView 的核心参数和实战示例,助你轻松实现流畅的索引列表。
72 7
云原生数据仓库AnalyticDB PostgreSQL同一个SQL可以实现向量索引、全文索引GIN、普通索引BTREE混合查询,简化业务实现逻辑、提升查询性能
本文档介绍了如何在AnalyticDB for PostgreSQL中创建表、向量索引及混合检索的实现步骤。主要内容包括:创建`articles`表并设置向量存储格式,创建ANN向量索引,为表增加`username`和`time`列,建立BTREE索引和GIN全文检索索引,并展示了查询结果。参考文档提供了详细的SQL语句和配置说明。
83 1
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
968 11
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
canal-starter 监听解析 storeValue 不一样,同样的sql 一个在mybatis执行 一个在数据库操作,导致解析不出正确对象
IntelliJ IDEA处理大文件SQL:性能优势解析
在数据库开发和管理工作中,执行大型SQL文件是一个常见的任务。传统的数据库管理工具如Navicat在处理大型SQL文件时可能会遇到性能瓶颈。而IntelliJ IDEA,作为一个强大的集成开发环境,提供了一些高级功能,使其在执行大文件SQL时表现出色。本文将探讨IntelliJ IDEA在处理大文件SQL时的性能优势,并与Navicat进行比较。
99 4
|
6月前
|
员工上网行为监控软件:SQL 在数据查询监控中的应用解析
在数字化办公环境中,员工上网行为监控软件对企业网络安全和管理至关重要。通过 SQL 查询和分析数据库中的数据,企业可以精准了解员工的上网行为,包括基础查询、复杂条件查询、数据统计与分析等,从而提高网络管理和安全防护的效率。
101 0

热门文章

最新文章

推荐镜像

更多
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等