简介
InnoDB支持以下几种常见的索引:
- B+树索引
- 哈希索引
- 全文索引
哈希索引
哈希索引是自适应的,存储引擎会根据表的使用情况,自动生成哈希索引,不可人为干预是否生成。
B+树索引
B+树是目前关系数据库中使用最为广泛的索 引,其中的B代表的是平衡(balance)。它是从平衡二叉树中演化而来,但其并不是二叉树。B+索引树只能找到所给键值所在的页,不能具体到行。
涉及到的数据结构
二分查找法
二分查找法,也称折半查找法,用来查找一组有序的记录数组中的某一个记录。
其基本思想是:将记录按有序化排列,在查找过程中按照跳跃式的方式查找,即以中间位置将有序区间分为两半,通过与中间位置比较的结果确定搜索值所在区间,以此类推,可以缩小搜索范围。
二叉查找树
在二叉查找树中,左子树的键值总是小于根的键值,右子树的键值总是大于根的键值,因此可以通过中序遍历可以得到有序输出。
为了得到相对较高的查找性能,应当使二叉查找树是平衡的。
如图所示:
图源自绘,太丑了,还请见谅。
由此,引出新的定义----平衡二叉树,或称AVL树。
平衡二叉树
首先符合二叉查找树的定义,其次必须满足任意结点的左右子树高度之差不大于1。
可以发现,平衡二叉树的查找性能很快,但是,维护平衡二叉树却需要一定的代价。通常来说,需要1次或多次的左旋或右旋来得到插入或更新后的树的平衡性。
插入新结点:
明显可以发现,维护一棵平衡二叉树是需要一定开销的,但因为平衡二叉树常用于内存结构对象中,因此开销较小。
B+树
B+树由B树和索引顺序访问方法演化而来,但是在现实使用过程中几乎已经没有使用B树的情况了。
B+树是为磁盘等直接读取的辅助设备而设计的一棵平衡查找树。在B+树中,所有记录节点都是按键值的大小顺序存放在同一层的叶子节点上,由各叶子节点指针进行连接。
先来看一个B+树,其高度为2,每页可存放4条记录,扇出(fan out)为5,如图所示:
明显可以看出,所有的记录都在叶子节点上,并且是顺序存放的,如果从最左边的叶子节点开始遍历,可以得到所有的键值顺序:5、10、15、20、25、30、50、55、60、65、75、80、85、90。
B+树的插入操作
B+树的插入必须保证插入后的叶子节点中的记录依然排序,同时需要考虑插入到B+树的三种情况,每种情况可能都会导致不同的插入算法。
Leaf Page 满 | Index Page 满 | 操作 |
No | No | 直接将记录插入到叶子节点 |
Yes | No | 1. 拆分 Leaf Page 2. 将中间的节点放入到 Index Page 中 3. 小于中间节点的记录放左边 4. 大于等于中间节点的记录放右边 |
Yes | Yes | 1. 拆分 Leaf Page 2. 小于中间节点的记录放左边 3. 大于等于中间节点的放右边 4. 拆分 Index Page 5. 小于中间节点的记录放左边 6. 大于中间节点的记录放右边 7. 中间节点放入上一层 Index Page |
第一种情况
第二种情况
第三种情况
可以看到,不管怎么变化,B+树总是会保持平衡。但是为了保持平衡对于新插入的键值可能需要做大量的拆分页(split)操作。
因为B+树主要应用于磁盘,页的拆分意味着磁盘的操作,所以应该在可能的情况下尽量减少页的拆分操作。
同样,B+树同样提供了类似于平衡二叉树的旋转(Rotation)功能。
旋转发生在 Leaf Page 已经满,但是其的左右兄弟节点没有满的情况下。这时的B+树并不会急于去做拆分页的操作,而是将记录移到所在页的兄弟节点上。
B+树的删除操作
B+树使用填充因子(fill factor)来控制树的删除变化,50%是填充因子可设的最小值。B+树的删除操作同样必须保证删除后叶子节点中的记录依旧排序。
叶子节点小于填充因子 | 中间节点小于填充因子 | 操作 |
No | No | 直接将记录从叶子节点删除 如果该节点还是 Index Page 的节点,用该节点的右节点代替 |
Yes | No | 合并叶子节点和它的兄弟节点,同时更新 Index Page |
Yes | Yes | 1. 合并叶子节点和它的兄弟节点 2. 更新 Index Page 3. 合并 Index Page和它的兄弟节点 |
第一种情况
第二种情况
第三种情况
关于B+树索引相关的知识,详见下回。