6_B+树索引
数据页结构
- 各个数据页组成一个双向链表;
- 每个数据页中的记录按照主键值升序组成一个单向链表;
数据页中查找记录
- 页目录二分查找槽;
- 遍历分组定位具体的记录;
数据页——》记录
如何快速定位到具体的数据页?——构建索引
一个简单的索引方案
类似给记录建立的页目录,可以给数据页也建立目录项
- 按照主键值升序;
- 数组槽 + 链表分组;
InnoDB中的索引方案
简易索引方案为了能根据主键值二分查找快速定位到具体的目录项,需满足所有目录项在物理存储器上连续存储。
但这样做有几个问题
- InnoDB使用页管理存储空间,一页的连续存储空间为16KB,无法存放大表中所有的目录项;——多级目录
- 时常会对记录进行增删,假设把页28中的记录都删除了,页28和目录项2都可以移除,但是需要把目录项3及之后都向前移动;——链表
目录项也是数据,类似于用户记录,也可以用页存储,细节有几点不同。
- 目录项中只有两个列主键、页号,存储空间比用户记录小,这种记录称为目录项记录;
- 记录头里
- record_type为1;
- 0:普通的用户记录;
- 1:目录项记录;
- 2:最小记录;
- 3:最大记录;
- min_rec_mask属性为1;
- 目录项记录且当前页主键值最小;
- record_type为1;
构建索引的方案是B+树
- 用户记录存放在B+树的最底层(第0层)的节点上,这些节点被称为叶子节点;
- 其余用来存放目录项的节点称为非叶子节点;
- 根据层数预估数据量
- 假设一个叶子节点可以存放100条用户记录;
- 假设一个非叶子节点可以存放1000条目录项记录;
- 那么3层B+树,最多能存放(1000) ^ 2 * 100 = 10^8,1亿条;
- 那么4层B+树,最多能存放1千亿条,所以一般情况下,B+树都不会超过4层;
- 根据主键快速查找一条记录,时间复杂度为logN;
- 最多查找3个目录项页和1个用户记录页;
- 目录项页根据页目录和分组快速定位到页号;
- 用户记录页根据页目录和分组快速定位到记录;
聚簇索引
上述介绍的B+树结构就是聚簇索引。
- 根据记录主键值的大小排序记录和页;
- 页内的记录按照用户记录的主键升序组成一个单向链表;
- 用户记录页按照用户记录的主键升序组成一个双向链表;
- 目录项记录页分为不同的层次,在同一层次中的目录项记录页按照用户记录的主键升序组成一个双向链表;
- 叶子节点存储完整的用户记录;
- 包括所有列的值,含隐藏列;
- 索引即数据,数据即索引;
根据二级索引查找完整用户记录的过程:
- 确定目录项记录页;
- 确定用户记录页;
- 定位到具体的记录,已经是完整的用户记录;
二级索引
按照非主键列的值进行查找,与聚簇索引的不同:
- 根据记录指定列值的大小排序记录和页;
- 目录项存储指定列值和页号;
- 叶子节点仅存储指定列值和主键值;
根据二级索引查找完整用户记录的过程:
- 确定目录项记录页;
- 确定用户记录页;
- 定位到具体的记录;
- 根据主键再去聚簇索引查找完整的用户记录;(回表)
联合索引
- 同时以多个列的大小作为排序规则;
- 联合索引本质上也是一个二级索引;
- 建立c2、c3列的联合索引与分别为c2、c3列建立索引是不同的;
注意事项
根页面固定不动