Sql Server 索引以及页和区
索引(Index),相信大家都知道就是给表中的数据添加了一个目录,使我们可以快速检索到我们想要的数据,但这个目录是什么?SqlServer又是如何管理的?要搞明白这些,我们就要先了解sqlserver数据库中的页(Page),区(Extents)的概念,如有不对的地方,欢迎拍砖指正。
页(Page)
- 页是数据存储的最本单位,SqlServer读写也是以页为单位进行的,即页是对数据管理的最小单位。页的大小8192B=8KB, 1MB存储128个数据页。
- 一个页具体如下图所示(图片引用MSDN),包含3部分:
- 头信息Page Hearder,占用96byte,存储关于页的信息,页码,页类型等;
- 数据行DataRows,具体存储的内容,占用8060byte;
- 行偏移表Row Offset Table,记录每个数据行第一个字节和页首(即96byte)的距离,顺序和页中行的顺序相反,占36byte;

页的类型本文涉及到的主要如下,其它页类型可自行查询MSDN
- Data:当行中的文本设置为 ON 时,具有除 text、ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 数据以外的所有数据的数据行。
- Index:索引条目。
- Text/Image:大型对象数据类型:(text、ntext、image、nvarchar(max)、varchar(max)、varbinary(max) 和 xml 数据),数据行超过 8 KB 时为可变长度数据类型列:(varchar、nvarchar、varbinary 和 sql_variant)
看到上面的Index页类型,我们就明白了索引和数据行一样也是存储在页中的,而且SqlServer针对不同的数据类型划分了不同的页类型,大数据类型(text,image,varchar(max),nvarchar(max))是存储在Text/Image页类型中的,该类型中还会存储单个数据行超过8KB时的可变长类型,即一页中只有一行,且数据行所占空间大小大于8060(即8192-96-36)byte,实际表中所有列的和不能大于8053byte(两者为啥相差7byte可参考此链接),这种情况下sqlServer会从最大长度的可变长度列开始动态将一个或多个列移动到 ROW_OVERFLOW_DATA 分配单元中的页,并在原始页中维护一个指针,如果后续数据行变小,SqlServer会将列再移回来。
区(Extents)
区是磁盘上连续的8个页,8*8KB=64KB。
- 混合盘区 Mixed Extents:每个页可能对应不同对象;
- 统一盘区 Uniform Extents:一个区中的8个页对应一个对象
索引(Index)
通过上面我们已经知道,索引也是存储在页上的,具有聚集索引(Clustered Index)的表是以B-tree(不是B减树。。。)结构组织的且数据按聚集索引顺序存储,否则存储在堆(Heap)上。B树上每一页称为一个索引节点,其中包含:
- 根节点:顶端节点,包含存有索引行的索引页;
- 中间级:根和叶节点之间的,同根节点包含存有索引行的索引页;
叶节点:底层节点,包含基础表的数据页;
索引行:包含一个键值和一个指针,该指针指向B树上的某一中间级页或叶级索引中的某个数据行。每级索引中的页均被链接在双向链接列表中.
非聚集索引(Nonclustered Index):具有和聚集索引相同的B树,区别如下:
- 数据行不会按照非聚集键排序和存储;
叶级节点指向的不是数据页而是索引页;
索引行:包含非聚集键和行定位符,此定位符指向聚集索引或堆中包含该键值的数据行.
表组织结构图(图片引用MSDN),最底下一行是三种分配单元,详细可直接前往MSDN连接查看。

一些思考:
通过以上内容,我们可以更直观,更容易总结出:
- 应该尽量把索引设置在较窄的列上,这样一个页上就可以存储更多的索引行,检索的效率就高了;
- 经常变动的列上不宜设置索引,因为会导致数据行及索引页的一连串修改调整;
- 建立多个索引可以提供表的查询性能,但同时也增加了修改数据的复杂度;
- 索引应尽量覆盖查询,因为数据全部存储在索引中,从而减少了磁盘I/O
...
最近花了一些时间整理了一下页,区,索引的相关知识点,并看了一些博客,感觉之前很多不懂的地方都豁然开朗了,其实相关内容还有很多 ,这里只是介绍了一部分,另外我们还是要多看官方文档(MSDN建议看英文的,中文翻译的好多地方让你很迷惑,看英文版反而能看懂)和大牛们的博客。
参考链接
- MSDN : https://docs.microsoft.com/zh-cn/sql/relational-databases/pages-and-extents-architecture-guide
- http://www.cnblogs.com/woodytu/p/4486193.html
Sql Server 索引以及页和区的更多相关文章
- SQL Server索引进阶:第四级,页和区
原文地址: Stairway to SQL Server Indexes: Level 4, Pages and Extents 本文是SQL Server索引进阶系列(Stairway to SQL ...
- 转: SQL Server索引的维护 - 索引碎片、填充因子
转:http://www.cnblogs.com/kissdodog/archive/2013/06/14/3135412.html 实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题 ...
- SQL Server索引的维护 - 索引碎片、填充因子 <第三篇>
实际上,索引的维护主要包括以下两个方面: 页拆分 碎片 这两个问题都和页密度有关,虽然两者的表现形式在本质上有所区别,但是故障排除工具是一样的,因为处理是相同的. 对于非常小的表(比64KB小得多), ...
- SQL Server 索引碎片产生原理重建索引和重新组织索引
数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲写入速度 页 ...
- [笔记整理]SQL Server 索引碎片 和 重建索引
铺垫知识点: 数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲 ...
- sql server 索引总结一
一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...
- T-SQL查询高级—SQL Server索引中的碎片和填充因子
写在前面:本篇文章需要你对索引和SQL中数据的存储方式有一定了解.标题中高级两个字仅仅是因为本篇文章需要我的T-SQL进阶系列文章的一些内容作为基础. 简介 在SQL Server中,存储数据 ...
- SQL Server索引 (原理、存储)聚集索引、非聚集索引、堆 <第一篇>
一.存储结构 在SQL Server中,有许多不同的可用排列规则选项. 二进制:按字符的数字表示形式排序(ASCII码中,用数字32表示空格,用68表示字母"D").因为所有内容都 ...
- SQL Server 索引结构及其使用(一)
转载:SQL Server 索引结构及其使用(一) 作者:freedk 一.深入浅出理解索引结构 实际上,您可以把索引理解为一种特殊的目录.微软的SQL SERVER提供了两种索引:聚集索引(clus ...
随机推荐
- SpringCloud @FeignClient的类注解@ReqestMapping无效报错:No message available","path":"/xxxx
最近在使用Feign组合微服务的时候发现在@FeignClient接口类上使用@ReqestMapping无效. 像下面的这个代码: @FeignClient("xxx") @Re ...
- 深刻理解iosBlock
深刻理解iosBlock ///一个控制器里的方法 - (void)setRefreshHeader { ACWeakSelf(self); self.tableView.mj_header = [M ...
- 搜索引擎的缓存(cache)机制
什么是缓存? 在搜索领域中,所谓缓存,就是在高速内存硬件设备上为搜索引擎开辟一块存储区,来存储常见的用户查询及其结果,并采用一定的管理策略来维护缓存区内的数据.当搜索引擎再次接收到用户的查询请求时,首 ...
- 阿里舆情︱舆情热词分析架构简述(Demo学习)
本节来源于阿里云栖社区,同时正在开发一个舆情平台,其中他们发布了一篇他们所做的分析流程,感觉可以作为案例来学习.文章来源:觉民cloud/云栖社区 平台试用链接:https://prophet.dat ...
- GOF 23种设计模式
设计模式目录 创建型 1. Factory Method(工厂方法) 2. Abstract Factory(抽象工厂) 3. Builder(建造者) 4. Prototype(原型) 5. Sin ...
- JavaScript获取当前日期
JavaScript获取当前日期 具体实现如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...
- 嵌入式linux------ffmpeg移植 编码H264(am335x编码H264)
[cpp] view plaincopy <pre name="code" class="cpp"><pre name="code& ...
- Java中用正则表达式找出数字
Java中用正则表达式找出数字 1.题目 String str = "fjd789klsd908434jk#$$%%^38488545",从中找出78990843438488 ...
- Vasya and Basketball CodeForces - 493C
Vasya follows a basketball game and marks the distances from which each team makes a throw. He knows ...
- 【转】Java中hashCode的作用
以下是关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值.支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表. hashCode ...