为什么 MySQL 采用 B+ 树作为索引?

为什么 MySQL 选择 B+ 树作为索引?

关于 MySQL 的 B+ 树,我们经常会被问这样的问题:

  • 为什么索引用 B+ 树,而不用红黑树?
  • 为什么索引用 B+ 树,而不用 B 树?
  • 为什么索引用 B+ 树,而不用哈希表?
  • 为什么索引用 B+ 树,而不用数组?
    ………………

你有没有想过,为什么 MySQL 数据库选择 B+ 树作为索引数据结构?这可不是随便选的,背后蕴藏着不少秘密。

要解释这个问题,其实不单单要从数据结构的角度出发,还要考虑磁盘 I/O 操作次数,因为 MySQL 的数据是存储在磁盘中的嘛。

MySQL 索引需要满足的条件

需要满足两点:

  • 尽可能少的磁盘 I/O 操作
  • 既要能高效的查询某一条记录,也要高效的进行范围查询

为什么索引用 B+ 树,而不用红黑树?

红黑树本质上是二叉树,而 B+ 树是多叉树,这样在存储相同数量量的情况下,红黑树的树会比 B+ 树的树高,由于 InnodB 引擎的数据都是存储在磁盘上的,如果树的高度越高,意味着磁盘 I/O 就越多,这样就会影响查询性能。
所以,InnodB 引擎选择了 B+树作为索引,而不是红黑树。

为什么索引用 B+ 树,而不用 B 树?

有三个角度来分析:

  • 磁盘 I/O 角度;

  • 范围查询角度;

  • 增删改查角度;

  • B+ 树的磁盘读写代价更低:B+ 树只有叶子节点才会存放索引和数据,非叶子节点只存放索引,而 B 树所有节点都存放索引和数据,而页的默认大小是固定的(16KB),如果不存储数据,就会存储更多的键值,相应的树的阶数就会更大,因此存储相同数据量的情况下, B+ 树可以比 B 树更加矮胖,查询叶子节点的磁盘 I/O 次数会更少

  • B+ 树便于范围查询:B+ 树所有叶子节点之间会用双向链表链表进行连接,使得 B+ 树在范围查询,排序查询,分组查询以及去重查询等变得更加简单,而 B 树只能通过中序遍历来完成,这会比 B+ 树涉及到更多的磁盘 I/O 操作

  • B+ 树增删改查更加稳定:B+ 树有大量的冗余节点,这些冗余数据可以让 B+ 树在插入、删除的效率都更
    高,比如删除根节点的时候,不会像 B 树那样会发生复杂的树的变化。另外,B+树把所有的用户记录都放到了叶子节点这一层,因此查询、插入、删除数据都需要走到最后一层,这不同于 B 树可能在任意一层找到数据,所以B+树更为稳定。

所以,InnodB 引擎选择了 B+树作为索引,而不是 B 树。

在这里插入图片描述

在这里插入图片描述

为什么索引用 B+ 树,而不用哈希表?

  • 哈希表的数据是散列分布的,不支持范围查询和排序
  • 哈希表存在哈希冲突的问题,哈希冲突严重的话会降低查询效率

MySQL 会有很多范围查询和排序的场景,虽然哈希表的搜索时间复杂度为 O(1),但是哈希表的数据都是通过哈希函数计算后散列分布的,所以哈希表索引不支持范围查询和排序操作,不支持联合索引最左匹配原则,如果重复键值比较多,还容易造成哈希碰撞导致效率进一步降低,而 B+ 树可以满足这些应用场景,因此选择了用 B+ 树。

为什么索引用 B+ 树,而不用数组?

用数组来实现线性排序的数据虽然简单好用,但是插入新元素的时候性能太低。

因为插入一个元素,需要将这个元素之后的所有元素后移一位,如果这个操作发生在磁盘中呢?这必然是灾难性的。因为磁盘的速度比内存慢几十万倍,所以我们不能用一种线性结构将磁盘排序。

其次,有序的数组在使用二分查找的时候,每次查找都要不断计算中间的位置。

为什么索引用 B+ 树,而不用二叉搜索树?

在特殊情况下,比如当每次插入的元素都是二叉查找树中最大的元素,二叉查找树就会退化成了一条链表,查找数据的时间复杂度变成了 O(n)

随着插入的元素越多,树的高度也变高,意味着需要磁盘 IO 操作的次数就越多,这样导致查询性能严重下降,再加上不能范围查询,所以不适合作为数据库的索引结构。

相关推荐

  1. 为什么MySQL会选择B+作为索引

    2024-07-15 04:00:02       24 阅读
  2. 索引原理;为什么采用B+

    2024-07-15 04:00:02       22 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 04:00:02       66 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 04:00:02       70 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 04:00:02       57 阅读
  4. Python语言-面向对象

    2024-07-15 04:00:02       68 阅读

热门阅读

  1. Python面试题:如何在 Python 中进行单元测试?

    2024-07-15 04:00:02       24 阅读
  2. git使用

    2024-07-15 04:00:02       20 阅读
  3. 哪个外汇平台可以交易美股?

    2024-07-15 04:00:02       19 阅读
  4. ubuntu disk

    2024-07-15 04:00:02       15 阅读
  5. 数据结构与算法基础篇--递归

    2024-07-15 04:00:02       20 阅读
  6. 来看一个14台480KW的充电站实际收入情况

    2024-07-15 04:00:02       20 阅读
  7. dify/api/models/workflow.py文件中的数据表

    2024-07-15 04:00:02       21 阅读
  8. Linux 命令集

    2024-07-15 04:00:02       23 阅读
  9. 代码随想录算法训练营第34天

    2024-07-15 04:00:02       25 阅读