上次写过每个数据页可以组成一个双向链表,每个数据页中的记录会按照主键值从小到大的顺序组成一个单向链表,每个数据页都会为它里面的记录生成一个页目录,通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速定位到指定的记录。
索引
首先我们需要建一个目录为了快速定位记录所在的数据页。需完成以下两点:
- 下一个数据页的用户记录的主键值必须大于上一个页中用户记录的主键值,在这过程中,需要移动一些记录来始终保持着这个状态一直成立。
- 给所有的页建立一个目录项。(页中的槽是针对页中的记录,目录项是针对所有的页)
由于这些大小为16KB的页在磁盘上可能并不挨着,在定位某个页时,需要给它们一个编制,每个页对应一个目录项,每个目录项包括两个部分。
页的用户记录中最小的主键值,用key
表示。
页号,用page_no
表示。
这些目录项和普通记录长得很像,不过目录项中两个列是主键和页号,所以复用了之前存用户记录的数据页来存储目录项。用记录头信息的 record_type
属性来区分是普通的用户记录还是目录项记录。
record_type
:这个属性表示当前的记录的类型,总共有4中类型:
- 0表示普通记录;
- 1表示B+树叶节点的目录项记录;
- 2表示
Infimum
记录; - 3表示
Supremum
记录;
还有一点区别是只有目录项记录,它的min_rec_flag
属性值才有可能为1,普通用户记录的min_rec_flag
只能为0。
为了根据主键值定位记录所在的目录项所在的页,把这些存储目录项的页再生成一个更高级的目录,就像一个多级目录一样,大目录里面嵌套小目录。如图:
这是一种组织数据的形式,名称为B+树。
真正的用户记录都在B+树最底层的节点上,这些节点也称为叶子节点或叶节点。
一般情况下,我们用到的B+树都不会超过4层。
聚簇索引
只能用在搜索条件是主键值才能发挥作用。
- 使用记录主键值的大小进行记录和页的排序。
- B+树的叶子节点存储的是完整的用户记录,就是指这个记录中所有列的值。
二级索引
若我们想要用别的搜索条件时,可以多建几棵B+树。
- 使用某列的大小进行记录和页的排序。
- B+树的叶子节点存储的并不是完整的用户记录,而是某列+主键这两个列的值。
- 目录项记录中不再是主键+页号的搭配,变成了某列+主键值+页号的搭配。
在B+树叶子节点定位到符合条件的用户记录之后,我们需要根据该记录中的主键信息到聚簇索引中查找完整的用户记录。这个携带主键信息到聚簇索引中重新定位完整的用户记录的过程也称为回表。每找到一条符合条件的记录就需要一次回表操作。
联合索引
同时以多个列的大小作为排列规则,同时为多个列建立索引。比如想让B+树按照c2和c3列建立索引。
- 先把各个记录按照c2列的大小进行排序。
- 在记录c2列相同的情况下,再采用c3列进行排序。
它的本质上也是一个二级索引。