1. 基本概念
1.1. 区
1.2. 页
1.3. 行
2.4. 堆(heap)
2.5. 分配单元
3. 索引的存储
3.1. B-树(Balance Tree)
3.2. 聚集索引
参考资料:
http://technet.microsoft.com/zh-cn/library/ms189051.aspx
Sql Server2005 技术内幕
1.1. 区
是管理空间的基本单位。一个区是八个物理上连续的页(即 64 KB),用来有效地管理页。所有页都存储在区中。
统一区,由单个对象所有。区中的所有 8 页只能由所属对象使用
混合区,最多可由八个对象共享。区中八页的每页可由不同的对象所有
![](http://hi.csdn.net/attachment/201111/22/0_13219438023nqu.gif)
1.2. 页
数据存储的基本单位。页的大小为8KB——
![](http://hi.csdn.net/attachment/201111/22/0_13219438428xeF.gif)
表头大小为96字节,含页码、页类型、上一页、下一页等信息
对于页中的每一行,每个行偏移表都包含一个条目。每个条目记录对应行的第一个字节与页首的距离。
页类型
|
内容
|
Data
|
当
text in row
设置为
ON
时,包含除
text
、
ntext
、
image
、
nvarchar(max)
、
varchar(max)
、
varbinary(max)
和
xml
数据之外的所有数据的数据行。
|
Index
|
索引条目。
|
Text/Image
| 大型对象数据类型:
数据行超过
8 KB
时为可变长度数据类型列:
|
Global Allocation Map
、
Shared Global Allocation Map
|
有关区是否分配的信息。
|
Page Free Space
|
有关页分配和页的可用空间的信息。
|
Index Allocation Map
|
有关每个分配单元中表或索引所使用的区的信息。
|
Bulk Changed Map
|
有关每个分配单元中自最后一条
BACKUP LOG
语句之后的大容量操作所修改的区的信息。
|
Differential Changed Map
|
有关每个分配单元中自最后一条
BACKUP DATABASE
语句之后更改的区的信息。
|
行中数据通常存储在IN_ROW_DATA分配单元的页(原始页)中;
单行数据大小超过8KB时,SQL Server 动态将一个或多个变长列移动到ROW_OVERFLOW_DATA 分配单元中的页中,原始页中维护指针;
Text/Image类型的列会被存储在LOB分配单元的页中,原始页中维护指针;
减少ROW_OVERFLOW_DATA有利于提高性能。
1.4. 填充因子(Fill Factor)
又称页填充度,即页的已用空间大小除以页的总大小。填充因子越小,对修改(插入、更新)操作越有利,对查询操作越不利。
非保持性状态,仅在创建或修改时起作用。可以在业务低潮时以稍小的填充因子重建索引,以降低业务高峰期页拆分的发生频率。
1.5. 页拆分
向已满的索引页中间插入新行时(在尾部插入数据不会引起页拆分),数据库将把该页中约一半的行移到新页中,以便为新行腾出空间。这种重组称为页拆分;
页拆分引发的行移动可能耗费大量资源(新行长度较大时可能引发多次的拆分),而且可能产生索引碎片;
通过设置索引的填充因子来重建索引可以减少页拆分的发生。
1.6. 索引碎片
索引碎片在磁盘IO方面影响查询性能;
页拆分产生碎片,即插入/更新操作可能导致碎片的产生;
索引碎片整理时需要考虑是否需要进行磁盘整理。
内部碎片
当索引页没有用到最大量时就产生了内部碎片。
在获取多个记录的查询中,内部碎片会导致需要访问更多的页才能够获得数据
外部碎片
索引页的物理顺序(在磁盘上的顺序)与逻辑顺序(索引键的顺序)不一致时,就产生了外部碎片
解析:索引碎片的产生和危害
有三个已满的索引页,页的物理顺序与逻辑顺序一致(如下图),此时不存在索引碎片
![](http://hi.csdn.net/attachment/201111/22/0_1321943891FJqf.gif)
当插入一条键值为5的记录时,需要将第一个页拆分,拆分后的情形如下:
![](http://hi.csdn.net/attachment/201111/22/0_1321943920ixee.gif)
此时,页1和新分配的页4上产生了内部碎片;键值7、8逻辑上在10之间,而物理上7、8所在的页却位于10所在页之后,故产生了外部碎片。
一个查询需要返回键值2-10之间的数据(2、4、5、7、8、10),如果没有内部碎片,两个页面就可以容纳这6条索引行,而现在却要访问3个页面才能获取到需要的数据;如果没有外部碎片,磁头只需从2开始顺序移动到10,现在在读完5之后要经过10、12…24移动到到7,读完8再经过7、24…12移动到10(此情形只会在索引的叶子级出现)。
2. 表的存储
2.1. 表
2.1. 表
表包含在一个或多个分区中,每个分区在一个堆或一个聚集索引结构中包含数据行。堆页或聚集索引页在一个或多个分配单元中进行管理。
![](http://hi.csdn.net/attachment/201111/22/0_1321943975kYWW.gif)
数据(IN_ROW_DATA)、行溢出(ROW_OVERFLOW_DATA)
2.2. 分区
当表或索引使用多个分区时,数据将被水平分区,以便根据指定的列将行组映射到各个分区。
分区可以降低索引文件/堆的大小,分区中的数据物理上更近,提高了IO效率。
分区可以并发的利用多磁盘
可以利用分区实现滑动窗口(Slide Window)。参考:http://blogold.chinaunix.net/u2/73798/showart_2524989.html
2.3. 聚集表
含有聚集索引的表。
数据实际是索引的一部分,数据页即索引的叶子页,故数据页间被双向链表链接。
![](http://hi.csdn.net/attachment/201111/22/0_13219440628NDW.gif)
不含聚集索引的表。
IAM(Index Allocation Map)与堆映射。数据行不按任何特殊的顺序存储,数据页也没有任何特殊的顺序。数据页不在链接列表内链接。
IAM页间有双向链接。
![](http://hi.csdn.net/attachment/201111/22/0_1321944116oouT.gif)
分配单元类型
|
用于管理
|
IN_ROW_DATA
| 包含除大型对象 (LOB) 数据以外的所有数据的数据行或索引行。
页的类型为
Data
或
Index
。
|
LOB_DATA
| 以下列一种或多种数据类型存储的大型对象数据: text、 ntext、 image、 xml、 varchar(max)、nvarchar(max) 、 varbinary(max) 或 CLR 用户定义类型 (CLR UDT)。
页的类型为
Text/Image
。
|
ROW_OVERFLOW_DATA
| 存储在超过 8,060 字节行大小限制的 varchar 、nvarchar 、 varbinary 或 sql_variant 列中的可变长度数据。
页的类型为
Text/Image
。
|
3.1. B-树(Balance Tree)
以页为节点左右平衡。
![](http://hi.csdn.net/attachment/201111/22/0_1321944158zf5t.gif)
数据本身是聚集索引的一部分(叶子节点)。索引中每个级别的页(包括叶级别的数据页)链接在一个双向链接的列表中,页内数据有序。通过使用键值来执行从一个级别到另一级别的导航。![]()
注:任何索引都只是逻辑排序,并不会物理排序。
3.3. 非聚集索引
非页级别同聚集索引,叶级别为索引页非数据页。叶级索引页中的索引行含:键值、行书签(BookMark)。在聚集索引上的表,书签即相应数据行的聚集索引键;堆上的表,书签为行标示符RID(文件号:页号:槽(slot)号)
![](http://hi.csdn.net/attachment/201111/22/0_13219443069g6I.gif)
注:堆上的非聚集索引数据页之间无链接
覆盖索引(include):一种特殊的非聚集索引——叶上包含数据信息
参考资料:
http://technet.microsoft.com/zh-cn/library/ms189051.aspx
Sql Server2005 技术内幕