MySQL:InnoDB存储引擎的B+树索引算法

很早以前,就从学校的图书馆借了MySQL技术内幕,InnoDB存储引擎这本书,但一直草草阅读,作的笔记也有些凌乱,趁着如今大四了,课程稍微少了一点,整理一下笔记,按照专题写一些,加深一下印象,不枉读了一遍书。与此同时,也加深一下对MySQL的了解,认识了原理,对优化的原则才有把握,对问题的分析才有源头。html

关于B+树数据结构

①InnoDB存储引擎支持两种常见的索引。

一种是B+树,一种是哈希。B+树中的B表明的意思不是二叉(binary),而是平衡(balance),由于B+树最先是从平衡二叉树演化来的,可是B+树又不是一个平衡二叉树。mysql

同时,B+树索引并不能找到一个给定键值的具体行。B+树索引只能找到的是被查找数据行所在的页。而后数据库经过把读入内存,再在内存中进行查找,最后获得查找的数据。算法

先从二分查找法提及:sql

    二分查找法的基本思想是,将记录排序(假如从小到大排序),而后采用跳跃式的方式进行查找,以有序数列的中点位置为比较对象,若是要找的元素小于该中点元素,那么查找左半部分,若是要找的元素大于该中点元素,那么久找右半部分。好比一组排好序的数:5 10 19 22 30 55 59 60 90, 若是我要查找60这个数字,那么先找30,发现30小于60,那么找30右半部分的中点59,发现59仍是小了,那么找59右边的数,从而找到了60,这样经过不断二分把查找须要的时间以指数级进行降低,算法效率到了Logn级别。数据库

 

再说一下平衡二叉树:数据结构

    131

 

        这是一幅平衡二叉树,左子树的值老是小于根的值,右子树的值老是大于根的键值,所以能够经过中序遍历(以递归的方式按照左中右的顺序来访问子树),所以遍历之后获得的输出是九、1七、2八、3五、3九、5六、6五、87。这样,若是要查找键值为28的记录,先找到根,而后发现根大于28,找左子树,发现左子树的根17小于28,再找下一层右子树,而后找到28。经过了3次查找找到了须要找的节点。可是若是二叉树节点分布很是不均匀,就像第二张图那样,那么若是要查找39这个节点的话,查找效率和顺序查找就差很少了,最差的结果就是查找65,那么二叉搜索树就会彻底退化成线性表。所以若是想要最大性能地构造一个二叉查找树,须要这颗二叉查找树是平衡的,平衡二叉树对于查找的性能是比较高的,可是不是最高的,只是接近最高的性能。要达到最好的性能,须要创建一颗最优二叉树,可是最优二叉树的创建和维护须要大量的操做,所以用平衡 二叉树就比较好。同时,平衡二叉树多用于内存结构对象中,所以维护他的开销相对较小。数据结构和算法

②为何使用B+树呢?

虽然二叉查找树和平衡二叉树都可以实现较快的数据查找,可是,因为数据库的内容是存在于磁盘上,而磁盘IO与内存IO相比,比内存IO慢了10^5~10^6倍,为了减小磁盘IO,提升检索速度,于是才用了B+树这种数据结构。换言之,B+树就是为磁盘或其余直接存取辅助设备而设计的一种多路查找树,是多叉树数据库设计

③什么是B+树,其特性是什么

B+树的概念仍是过于复杂,直接上图比较合适,来一张维基百科上的截图:性能

从上面能够看出,全部记录的节点都在页节点中,而且是顺序存放的,若是咱们从最左边的节点开始遍历,能够获得的全部键值的顺序是:一、二、三、四、五、六、7。优化

在B+树中,全部记录节点都是按照键值的大小顺序存放在同一层的叶节点中,各个叶子节点经过指针进行链接。因为一个节点中存放了多条的数据,那么检索的时候,进行的磁盘IO次数将会少掉不少。

在B+树插入的时候,为了保持平衡,对于新插入的键值可能须要作大量的拆分页操做,而B+树主要用于磁盘,所以页的拆分意味着磁盘操做,所以应该在可能的状况下尽可能减小页的拆分。所以,B+树提供了旋转的功能。至于旋转和删除等内容,过于复杂,这篇笔记先不作记录。只是了解使用B+树的缘由以及B+树的特性。

关于索引

InnoDB存储引擎使用汇集索引,实际的数据行和相关键值保存在一块。于是,在InnoDB中要使用索引访问数据始终须要两次查找,而不是一次。由于索引叶子节点中存储的不是行的物理位置,而是主键的值。即:二次索引-->主键-->数据的叶子-->经过数据叶字节点中的page directory找到数据行。

由于每一张InnoDB的表都会有一个主键索引,可是若是没有显式指定怎么办?若是没有手工去指定主键索引的话,那么,InnoDB引擎会指派一个unique的列做为主键,若是没有unique的字段的话,那么便会自动生成一个隐含的列做为主键。

因此,在在InnoDB的设计中,应该尽量的使用一个与业务无关auto_increment的自增主键,而不要去使用uuid之类的随机(无序)的汇集键。同时,因为全部的索引都使用主键的索引,若是主键索引过长,也会使辅助索引相应的变大。

汇集索引的存储并非物理上的连续,而是逻辑上连续的。一方面,页经过双向链表链接,页按照主键的顺序排列;另外一方面,每一个页中的记录也是经过双向链表进行维护,物理存储上能够一样不按照主键存储。

对于目前的MySQL来讲,全部的对于索引的添加或者删除操做,MySQL数据库都是要先建立一张新的临时表,而后再把数据导入临时表,再删除原来的表,而后再把临时表命名为原来的表。因此,若是一张表中数据太多的话,那么后期添加删除索引须要花费很长的时间,于是最好在数据库设计初期便设计好索引。

还有,虽然InnoDB存储引擎从版本innoDB Plugin开始,支持一种称为快速索引建立的方法,可是这种方法只限定于辅助索引,对于主键的建立和删除仍是须要重建一张表。

 

更好的资料:

[1]敲代码的张扬的《MySQL索引背后的数据结构和算法》

[2]《MySQL技术内幕:InnoDB存储引擎》

相关文章
相关标签/搜索