《MySQL技术内幕:SQL编程》读书笔记 -- 索引 -- 索引算法
一、二分法查找
二分法查找也称折半查找,其基本思想:将一组记录有序排列,先以有序数列中点位置做比较,如果目标数小于中点位置,则将待查序列缩小为做半部分,否则为右半部序列,通过一次次的递归查找,最终找到目标数,例如对于5、10、19、21、31、37、42、48、50、52查找48这条记录:
如上图所示,找到48只需要3次查找,而顺序查找的话,需要8次查找,所以加快了查找速度。
二、二叉查找树
二叉树是一种经典的数据结构,下图是一棵二叉查找树;二叉查找树中,左子树的键值总是小于根的键值,右子树的键值总是大于根的键值,因此可以通过中序遍历得到有序值:2、3、5、6、7、8。
如下图,如果想要找到8,首先和根节点比较,8大于6,在右子树中查找,8大于7,继续在右子树中查找,经过三次找到8;如果顺序查找的话,需要6次才能找到。
三、平衡二叉树
二叉树存在的问题:二叉树可以任意构造,同样是2、3、5、6、7、8;也可以构造成下图这样;显然这样的话查找效率会慢很多,因此要构造一棵最大性能的二叉树,必须让这个二叉树平衡,因此引入了新定义:平衡二叉树,又称AVL树。
平衡二叉树的定义:首先必须满足二叉树的定义,其次必须满足任何节点的两棵子树的高度最大差不能大于1;平衡二叉树的查询速度的确很快,但是维护平衡二叉树的代价也是比较大的,通常需要经过一次或多次的左旋转或右旋转来得到经过插入或更新后的平衡二叉树,比如向下图的二叉树种插入新值9:
四、B+树
B+树是由B树和索引顺序访问方法演化而来的,在B+树种,所有的记录节点都按顺序存放在叶子节点上,各叶子节点通过指针连接,下图为一个B+树:
1、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 |
1)插入键值28,符合第一种情况,直接插入,插入后的结果如下;
2)继续插入键值70,这时候Leaf Page 已经满了,Index没满,符合第二种情况,插入后的结果如下;
3)继续插入键值95,这个时候Leaf Page和Index Page都已经满了,符合第三种情况,插入后的结果如下:
可以看到,无论怎样,B+树始终保持平衡,但是在保持平衡就意味着要做大量的分页拆分,而B+树主要是用于磁盘中,所以拆分意味着磁盘操作,为了增加性能,应该尽量减少磁盘操作,所以B+树也提供了旋转功能,旋转发生在Leaf Page已满,而其左右兄弟并没有满的情况下,因此,上面插入键值70时,并不需要分页拆分,只需要旋转即可实现,即:将所在页的记录移到兄弟页上,结果结果如下:
2、B+树删除操作
B+树的删除操作是基于填充因子来控制树的删除变化,填充因子能够设置的最小值为50%,和插入一样,在删除后叶子节点上的记录依然保持顺序排列,同时需要考虑以下三种情况,每种情况导致插入的算法不同:
叶子节点小于填充因子 | 中间节点小于填充因子 | 操作 |
No | No | 直接将记录从叶子节点删除,如果该节点是Index Page,用该节点的右节点代替 |
Yes | No | 合并叶子节点和他的兄弟节点,同时更新Index Page |
Yes | Yes |
1、合并叶子节点和他的兄弟节点 2、更新Index Page 3、合并Index Page和他的兄弟节点 |
1)接着上面的的B+树,先删除键值70,符合第一种情况,直接从B+树删除即可,结果如下:
2)接着删除键值25,也符合第一种情况,但是键值25是Index Page,所以删除键值25后,用他的右节点28代替,结果如下:
3)接着删除键值60的,因为删除Leaf Page中键值为60的记录后,填充因子小于50%,这时需要做合并操作,同样的在删除Index Page的相关记录后,需要做Index Page的合并操作,结果如下: