MySQL为何选择B+树作为索引结构

一、概述

MySQL有多种存储引擎,每种引擎都有自己的特点,实际应用中我们可以根据自己的需要选择。常用的存储引擎有MyISAM、InnoDB等,其中MyISAM是MySQL数据库自带引擎,InnoDB是其他公司以插件的形式嵌入MySQL。

我们知道,MySQL数据存储在磁盘,磁盘IO会成为最大的性能瓶颈,因此设计的目标应该是尽量减少IO访问次数;而IO次数的操作跟树的高度成正比,树的高度越高,每次执行增删改查的IO操作次数越多,因此我们在选择、设计的时候需要树高将作为一个重要参考项。

本文通过对几种树形结构的特点进行分析、比较,说明为何MySQL选择B+树作为索引结构。



二、树形结构分析、比较

1、二叉查找树

二叉查找树(BST,Binary Search Tree)也叫二叉排序树。

特点

  • 任意节点的左子树上所有节点值不大于根节点的值。
  • 任意节点的右子树上所有节点值不小于根节点的值。
    在这里插入图片描述
    应用场景
    二叉查找树一般常用于快速查找。

时间复杂度
由于查询时间取决与树高,因此平均时间复杂度是O(lgN)。
而特殊情况下,二叉查找树可能会退化为链表,此时时间复杂度为O(N)。
在这里插入图片描述
如果退化为链表,查询效率就非常低。因此二叉查找树的不平衡时,不适合于MySQL。
为了解决这个问题,我们引入平衡二叉树。


2、平衡二叉树(AVL)

特点
除了包含二叉查找树的特点外,主要特点是:任何节点的两个子树的高度最大差为1。

在这里插入图片描述
上图非AVL图,9号子树与3、5号子树的高度差为2;AVL图9号子树与4、7子树的高度差为1。

时间复杂度
平衡二叉树实现平衡的关键在于旋转操作。
插入和删除操作都有可能破坏二叉树的平衡,这时需要通过一次或多次树旋转来重新平衡这个树。
1)插入数据:最多只需要1次旋转。
2)删除数据:AVL需要维护从被删除节点到根节点这条路径上所有节点的平衡,旋转次数为O(lgN)。

这样,AVL树在删除数据时效率就比较低;如果删除操作越多,维护平衡所需的时间代价越大,因此旋转耗时过长情况下,不太适合MySQL增删改查操作。

应用场景
适合插入和删除次数比较少,但查找次数比较多的情况。


3、红黑树

特点
红黑树只需确保从根到叶子的最长的可能路径不多于最短的可能路径的2倍长,无须像平衡二叉树那样严格的平衡要求。用来换取增删节点时候旋转次数的降低,任何不平衡都会在3次旋转之内解决。

应用场景
多用于搜索、插入、删除操作多的情况。

与AVL的比较
1)由于红黑树比AVL稍微不平衡多一层,因此红黑树的查询性能可能会比相同内容的AVL要低。
2)红黑树插入、删除操作性能优于AVL,AVL树每次插入、删除会进行大量的平衡度计算,而红黑树为了维持红黑树性质所做的红黑变换和旋转的开销,相较于AVL树小得多。
3)总的来说,红黑树的统计性能高于AVL。

对于在内存中的数据操作,红黑树的表现还是非常不错的。不过对于在磁盘等存储设备中的数据操作,红黑树表现就没那么好了。因为红黑树的高度,对于磁盘存储类的设备来说,还是太高了。


4、平衡多路查找树(B树)

平衡多路查找树(B-Tree),是为磁盘等外存储设备设计的一种平衡查找树。与二叉树相比,B树的每个非叶节点可以有多个子树。因此当总节点数量相同时,B树的高度远远小于AVL树和红黑树。

特点
阶数(Order)是B树最重要的概念,对于一颗m阶B树,需要满足以下条件:
1)每个节点最多包含m个子节点。
2)如果根节点包含子节点,则至少包含2个子节点;除了根节点外,每个非叶节点至少包含m/2个子节点。
3)拥有k个子节点的非叶节点将包含k-1条记录。
4)所有叶节点都在同一层。
在这里插入图片描述

可以看出,B树的定义,主要是对非叶节点的子节点数量和记录数量的限制。

B树的优势除了树高小,还有对访问局部性原理的利用。所谓局部性原理,是指当一个数据被使用时,其附近的数据有较大概率在短时间内被使用。B树将键相近的数据存储在同一个节点,当访问其中某个数据时,数据库会将该整个节点读到缓存中;当它临近的数据紧接着被访问时,可以直接在缓存中读取,无需进行磁盘IO;换句话说,B树的缓存命中率更高。

B树在数据库中有一些应用,如mongodb的索引使用了B树结构。但是在很多数据库应用中,使用了是B树的变种B+树。


5、B+树

B+Tree是在B-Tree基础上的一种优化,使其更适合实现外存储索引结构。

与B树的区别:
1)B树每个节点,包括叶节点和非叶节点都存储所有数据(包括key、value),B+树非叶节点只存储key,只有叶子节点存储value。
2)B树一条记录只会出现一次,B+树的键则可能会重复出现。
3)B+树的叶节点之间通过双向链表链接。
4)B树的非叶节点,记录数比子节点个数少1;B+数中记录数与子节点个数相同。

在这里插入图片描述

B+树与B树相比,优势有:

  • 更少的IO次数:B+树的非叶节点只包含键,而不包含真实数据,因此每个节点存储的记录个数比B数多很多(即阶m更大),因此B+树的高度更低,访问时所需要的IO次数更少。此外,由于每个节点存储的记录数更多,所以对访问局部性原理的利用更好,缓存命中率更高。

  • 更适于范围查询:在B树中进行范围查询时,首先找到要查找的下限,然后对B树进行中序遍历,直到找到查找的上限;而B+树的范围查询,只需要对链表进行遍历即可。

  • 更稳定的查询效率:B树的查询时间复杂度在1到树高之间(分别对应记录在根节点和叶节点),而B+树的查询复杂度则稳定为树高,因为所有数据都在叶节点。

B+树劣势:
由于键会重复出现,因此会占用更多的空间。
但是与带来的性能优势相比,空间劣势往往可以接受,因此B+树的在数据库中的使用比B树更加广泛。

参考:https://www.php.cn/mysql-tutorials-436372.html

猜你喜欢

转载自blog.csdn.net/locahuang/article/details/110436875