如果一张表没有聚集索引,那么它被称为“堆集”(Heap) 。这样的表中的数据行没有特定的顺序,所有的新行将被添加的表的末尾位置 。
4.聚集索引
在聚集索引中,叶结点也即数据结点,所有数据行的存储顺序与索引的存储顺序一致 。

文章插图
1)聚集索引与查询操作
如上图,我们在名字字段上建立聚集索引,当需要在根据此字段查找特定的记录时,数据库系统会根据特定的系统表查找的此索引的根,然后根据指针查找下一个,直到找到 。
例如我们要查询“Green”,由于它介于[Bennet,Karsen],据此我们找到了索引页1007,在该页中“Green”介于[Greane, Hunter]间,据此我们找到叶结点1133(也即数据结点),并最终在此页中找以了目标数据行 。
此次查询的IO包括3个索引页的查询(其中最后一次实际上是在数据页中查询) 。
这里的查找可能是从磁盘读取(Physical Read)或是从缓存中读取(Logical Read),如果此表访问频率较高,那么索引树中较高层的索引很可能在缓存中被找到 。所以真正的IO可能小于上面的情况 。
2)聚集索引与插入操作
最简单的情况下,插入操作根据索引找到对应的数据页,然后通过挪动已有的记录为新数据腾出空间,最后插入数据 。
如果数据页已满,则需要拆分数据页(页拆分是一种耗费资源的操作,一般数据库系统中会有相应的机制要尽量减少页拆分的次数,通常是通过为每页预留空间来实现):
- 在该使用的数据段(extent)上分配新的数据页,如果数据段已满,则需要分配新段 。
- 调整索引指针,这需要将相应的索引页读入内存并加锁 。
- 大约有一半的数据行被归入新的数据页中 。
- 如果表还有非聚集索引,则需要更新这些索引指向新的数据页 。
- 如果新插入的一条记录包含很大的数据,可能会分配两个新数据页,其中之一用来存储新记录,另一存储从原页中拆分出来的数据 。
- 通常数据库系统中会将重复的数据记录存储于相同的页中 。
- 类似于自增列为聚集索引的,数据库系统可能并不拆分数据页,页只是简单的新添数据页 。
删除行将导致其下方的数据行向上移动以填充删除记录造成的空白 。
如果删除的行是该数据页中的最后一行,那么该数据页将被回收,相应的索引页中的记录将被删除 。
如果回收的数据页位于跟该表的其它数据页相同的段上,那么它可能在随后的时间内被利用 。
如果该数据页是该段的唯一一个数据页,则该段也被回收 。
对于数据的删除操作,可能导致索引页中仅有一条记录,这时,该记录可能会被移至邻近的索引页中,原索引页将被回收,即所谓的“索引合并” 。
5.非聚集索引
非聚集索引与聚集索引相比:
- 叶子结点并非数据结点
- 叶子结点为每一真正的数据行存储一个“键-指针”对
- 叶子结点中还存储了一个指针偏移量,根据页指针及指针偏移量可以定位到具体的数据行 。
- 类似的,在除叶结点外的其它索引结点,存储的也是类似的内容,只不过它是指向下一级的索引页的 。
而对于非聚集索引,则是密集索引,在数据页的上一级索引页它为每一个数据行存储一条索引记录 。
对于根与中间级的索引记录,它的结构包括:
- 索引字段值
- RowId(即对应数据页的页指针+指针偏移量) 。在高层的索引页中包含RowId是为了当索引允许重复值时,当更改数据时精确定位数据行 。
- 下一级索引页的指针
- 索引字段值
- RowId

文章插图
1)非聚集索引与查询操作
针对上图,如果我们同样查找“Green”,那么一次查询操作将包含以下IO:3个索引页的读取+1个数据页的读取 。
同样,由于缓存的关系,真实的IO实际可能要小于上面列出的 。
2)非聚集索引与插入操作
如果一张表包含一个非聚集索引但没有聚集索引,则新的数据将被插入到最末一个数据页中,然后非聚集索引将被更新 。
推荐阅读
- 金骏眉你真的了解吗? 金骏眉属于什么茶
- 卫生间装修风水注意问题 色彩装修需了解
- 汕头青袍彻底颠覆人们红袍印象
- 刚来的大神彻底干掉了代码中的if else...
- 开发者必须了解的22个常用小程序开发api接口
- 通过监控DNS记录,来保护网站的几种方式?你需要了解
- 通过路由器配置DHCP服务实现IP地址分配,一分钟了解下
- 益生菌是什么?一起来了解下
- 高速开车的禁忌你了解吗?这五大要点要牢记
- 了解每种茶叶的特性 泡出好茶
