引言

我们知道mysql的索引模型是B+树,每个索引在innodb引擎中其实都是一个B+树,面试中经常会问为什么mysql不使用适用于磁盘访问而设计的B树而是用B+树,既然要聊为什么,那么首先要对二者有一个清晰的了解。

B树
每个节点都存储key和data,所有节点组成这棵树,并且叶子节点指针为null。

根节点至少有两个子节点
每个节点有M-1个key,并且以升序排列
位于M-1和M key的子节点的值位于M-1 和M key对应的Value之间
其它节点至少有M/2个子节点

mysql 树形存储过程 mysqlb+树_结点

B+树
只有叶子节点存储data,叶子节点包含了这棵树的所有键值,所有叶结点构成一个有序链表,非叶子节点只存储导航信息。

B+树是对B树的一种变形树,它与B树的差异在于:

有k个子结点的结点必然有k个关键码;

非叶结点仅具有索引作用,跟记录有关的信息均存放在叶结点中。

树的所有叶结点构成一个有序链表,可以按照关键码排序的次序遍历全部记录。

mysql 树形存储过程 mysqlb+树_b树_02

总结
对于mysql查找数据而言,无非是非为两大类,一类是k-v查询,通俗讲就是单行查询,另一类是范围查询,也就是多行查询。
我们来讨论在进行这两类查询的时候B树和B+树都有什么区别

对于k-v查询来说,B树和B+树其实都没啥问题,假如我们要查询0005这个数据,B树反尔比B+树查询出结果来的要快。
对于范围查询来说,区别比较大了,对于B+树来说,只需要通过索引找到范围查询的左边界,然后通过链表遍历即可。而对于B树来说,对于每个数据来说都需要进行反复的索引判断,效率远不如B+树的遍历来的快。

B+ 树的优点在于:
由于B+树在内部节点上不包含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子节点上关联的数据也具有更好的缓存命中率。
B+树的叶子结点都是相连的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
但是B树也有优点,其优点在于,由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速