为什么 MySQL 默认的存储引擎 InnoDB 会使用 B+ 树来存储数据?

​前言

关于索引,大家都知道能提高查询效率,是能高效获取数据的数据结构。但是为什么MySQL选择使用B+树?关于这个问题很多人都有自己的理解,但都回答得不够完整,也有人只是讲了B+树和B树的区别,并没有真正回答MySQL为什么选择B+树这个问题。想要知道答案,我们接下来会深入分析各种场景下不同数据结构的优缺点。

首先需要澄清的一点是,MySQL 跟 B+ 树没有直接的关系,真正与 B+ 树有关系的是 MySQL 的默认存储引擎 InnoDB,MySQL 中存储引擎的主要作用是负责数据的存储和提取,除了 InnoDB 之外,MySQL 中也支持 MyISAM 作为表的底层存储引擎。


正文

为什么 MySQL 默认的存储引擎 InnoDB 会使用 B+ 树来存储数据,相信对 MySQL 稍微有些了解的人都知道,无论是表中的数据(主键索引)还是非主键索引最终都会使用 B+ 树来存储数据,其中前者在表中会以 <id, row> 的方式存储,而后者会以 <index, id> 的方式进行存储,这其实也比较好理解:

  • 在主键索引中,id 是主键,我们能够通过 id 找到该行的全部列;

  • 在非主键索引中,索引中的几个列构成了键,我们能够通过索引中的列找到 id,如果有需要的话,可以再通过 id 找到当前数据行的全部内容;


在具体分析 InnoDB 使用 B+ 树背后的原因之前,我们需要为 B+ 树找几个假想敌,因为如果我们只有一个选择,那么选择 B+ 树也并不值得讨论,找到的两个假想敌就是 B 树和哈希,相信这也是很多人会在面试中真实遇到的问题,我们就以这两种数据结构为例,分析比较 B+ 树的优点。

读写性能

只访问或者修改一条数据的SQL时

select * from user where id=1;

  • 使用B+树作为底层的数据结构,时间复杂度是O(log n);

  • 使用哈希作为底层的数据结构,时间复杂度是O(1);

看起来使用哈希非常美好,但是我们如果使用如下所示的SQL时

select * from user where id>10 order by create_time desc;select * from user where id>10 and crete_time>1646636628;

此场景下,如果使用哈希作为底层的数据结构,可能就无法快速处理了,因为它对于范围查询或者排序的性能非常差,只能进行全表扫描并依次判断是否符合结果。

全表扫描对于MySQL是无法接受的糟糕结果,这其实意味着我们选择的数据结构没有任何效果。

哈希与B+树

B 树和 B+ 树在数据结构上其实有一些类似,它们都可以按照某些顺序对索引中的内容进行遍历,对于排序和范围查询等操作,B 树和 B+ 树相比于哈希会带来更好的性能,当然如果索引建立不够好或者 SQL 查询非常复杂,依然会导致全表扫描。

数据加载

使用哈希作为底层的数据结构无法高效的处理常见的范围查询和排序等操作,但是使用B+树或者B树作为底层的数据结构能非常高效的的应对。既然这样,为什么没有选择B树?其实原因很简单:

B 树能够在非叶子节点中存储数据,但是这也导致在查询连续数据时可能会带来更多的随机 I/O,而 B+ 树的所有叶子节点可以通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O;

查询数据

画外音:“这里的随机I/O指MySQL查询数据时,CPU发现当前数据位于磁盘而不是内存中,这时会触发I/O操作将数据以页为维度加载到内存中,然而数据从磁盘读取到内存中的代价是巨大的。”

b树与b+树

另外是由于数据结构的不同,查找范围数据的方式不同。B树非叶子节点存储数据,所有节点都可能包含数据,我们总要从根节点向下遍历子树找到满足条件的数据行,这个特点带来了更多的随机I/O,也是B树最大的性能问题。

B+树中不存在这个问题,通过一个 B+ 树最左侧的叶子节点,我们可以像链表一样遍历整个树中的全部数据,我们也可以引入双向链表保证倒序遍历时的性能。


总结

我们在这里重新回顾一下 MySQL 默认的存储引擎选择 B+ 树而不是哈希或者 B 树的原因:

  • 哈希虽然能够提供 O(1) 的单数据行操作性能,但是对于范围查询和排序却无法很好地支持,最终导致全表扫描;

  • B 树能够在非叶子节点中存储数据,但是这也导致在查询连续数据时可能会带来更多的随机 I/O,而 B+ 树的所有叶子节点可以通过指针相互连接,能够减少顺序遍历时产生的额外随机 I/O;


参考资料

  • What is the difference between Mysql InnoDB B+ tree index and hash index? Why does MongoDB use B-tree[https://medium.com/@mena.meseha/what-is-the-difference-between-mysql-innodb-b-tree-index-and-hash-index-ed8f2ce66d69]

  • B-Tree vs Hash Table[https://stackoverflow.com/questions/7306316/b-tree-vs-hash-table]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值