vlambda博客
学习文章列表

Mysql为什么使用B+树而不是B树?

先有B树,后有B+树。但是B+树比B树更为出名,其原因在于Mysql使用B+树作为实现索引的数据结构。B+树和B树不同的地方有两个:1)B+树的非叶子节点不包括指向数据的指针,也就是非叶子节点只有索引数据;2)B+树的所有叶子节点包括了指向数据的指针,并且叶子节点是按索引顺序单向链在一起的。B+树的结构如下图:


Mysql为什么使用B+树而不是B树作为实现索引的数据结构呢?原因有三点,在说明这三点之前,需要说明一下Mysql使用B+树的时候,其结点的大小是有设计的。由于B+树用来索引数据,因此Mysql把B+树每个结点的大小设计成内存页的大小一致,这么做的目的是让每次获取一个结点的数据时不需要跨内存页,增加了效率。这使得B+树每个节点能容纳的数据是有限的,这个点和下述的三个原因紧紧相关。


【原因一】 B+树的叶子节点链在一起增加范围查询的效率


为什么只有叶子节点存储数据指针呢?这样不是让每次查询都要查到叶子节点才能返回数据吗?背后的原因在于这么做虽然增加单次查询可能要多判断的情况,但是如果配合将叶子节点链在一起的方法,可以极大提高范围查询的效率。


以下图B树为例,如果要查询大于2的数据,需要先找到2这条数据,再进行中序遍历依次找出3、4、5、6、7这些数据,这个过程的时间复杂度是O(n),但是由于需要暂存节点信息,因为空间复杂度是O(n),在每个节点占一个内存页大小的情况并不一定是好事。

但是B+树通过将叶子节点链起来,可以在空间复杂度为O(1)的方向中进行范围遍历;


【原因二】B+树的非叶子结点可以放更多数据,从而让树高更低,增加查询效率


由于每个节点固定占一个内存页大小,B树的每个节点都包括了指向数据的指针,而B+树仅叶子结点包括了指向数据的指针,所以B+树的非叶子结点可以存储更多的索引数据,这样树的层高更低了,在节点占一个内存页的情况下,可以减少IO次数,访问效率自然也更高了。


【原因三】查询、插入、删除数据的时间稳定


有时候,系统的性能不一定要最好,但是一定要稳定。B+树把所有指向数据的指针都放到了叶子节点,因此查询、插入、删除数据都需要走到最后一层,这不同于B树可能在任意一层找到数据。所以B+树更为稳定。