总揽
大家好,我是骄阳。
我们面试的时候,经常会遇到一个经典问题:mysql存储引擎为什么选择b+树?包括我自己面试的时候,也遇到过很多次这个问题。那我们应该如何回答这个问题?
我比较建议从两个角度来回答:
第一个就是别的树为什么不可以?
第二个就是b+树为什么能成为天选之子。
一、为什么不选择别的树?
首先就是第一个方面:为什么别的树不可以?
1、二叉树为什么不可以?
我们先来看下二叉树为什么不可以?
二叉树是我们接触的树中比较简单的树,
我们先来看下二叉树的数据结构
这个网站都知道吧,数据结构的可视化工具,安利一下~不知道也没有关系,我把链接放下面:
我们试想一种比较常见的场景:如果是单边递增的数据,数据结构会变成什么样?
很容易想到对不对,就是这条直线无限延伸下去。
那么思考一下,会有什么问题?
查找速率会变低,为什么?
比如我们想找到这个007的数据,思考一下,我们需要和磁盘做多少次交互?
需要7次
这种需要和磁盘频繁交互的方式,肯定是不友好的,几乎和全表扫描没什么区别了。
这就是不能用二叉树的原因。
2、红黑树为什么不可以?
紧接着我们来看下红黑树为什么不可以?红黑树是我们最熟悉的树,hashmap底层就用了红黑树,也经常在面试中被疯狂拷问
我们先来看下红黑树的结构。
红黑树又叫平衡二叉树,比二叉树的效率要高。
为什么说红黑树效率要高?
同样的自增场景,很明显查询次数变少了,和磁盘交互的次数也少了,效率就高了
既然mysql没有选择红黑树,那么想一下红黑树有什么弊端?
弊端:当数据比较多的时候,树的高度会比较高,效率比较低。
我们看下下图,只是12个数据,层高就达到5了
肯定有人疑惑,层高高,为什么效率低?
我们查找数据,通常都是按照最坏的情况来算的,这里比如查找12,至少要交互5次。
也就是说:如果层高是n,至少也要找n次
像有些互联网公司数据量都比较大,o(n)这种效率肯定是不合格的。
3、b树为什么不可以?
下面让我们隆重介绍一下b树,我们今天的主角:b+树,一听名字,就知道是b树的一个变种。
既然他们这么相似,b树为什么不可以?
老样子,我们先看下数据结构,b树和b+树这两个数据结构,我比较建议放在一起看。
两者的区别是不是很直观:
b+树叶子节点之间有指针
b+树非叶子节点没有数据,只有索引
上面我们说红黑树是因为层高比较高,那么b树和b+树又是什么样的呢?
如果让你设计数据结构,同等数量级的数据,怎么能让层高更低?
是不是让前几层尽可能地多放数据?
我们先了解一个知识点,mysql的innodb的存储引擎默认的节点大小是16kb
那么我们的树是由节点组成的,只要每个节点存储的数据越多,树高是不是就越低。
那么b树和b+树,哪个树的节点存储的数据更多?
b+树
为什么?
因为b树的根节点放了数据,那么每一节点放的数据(索引)就更少,数据量很大的时候,树高就更高。
就像我们上面说的,树高更高的,效率更低。
这就是不选择b树的原因。
二、b+树为什么能成为天选之子?
下面我们来看下第二方面,为什么b+树能够成为天选之子?
除了我们上面的说的,层高更低,还有别的特别之处吗?
显然是有的,我们上面提到过:b+树叶子节点之间有指针。
那么这样优化,有什么好处呢?
我们经常会遇到需要查询一个范围的数据
比如x>15
我们先从根节点开始查找,快速定位到15,虽然b树和b+树都会把数据按照大小排序,但是因为b+树是有指针的,所以从15开始,向右开始查找,就是我们要找的数据,并且每一页查找完之后,再根据页之间的指针,快速找到下一页。
而b树,虽然每一页也是排好序的,但是因为页之间没有指针,所以要想找到下一页,还需要从根节点从新找一遍,速度就比较慢。
这里再拓展一点:
我们上面提到:mysql的innodb的存储引擎默认的节点大小是16kb
与此同时,InnoDB每一次磁盘I/O,读取的都是 16KB的整数倍的数据。也就是每次读取一个叶子节点,或者n个叶子节点。
也就是说b+树这种数据结构,可以充分利用磁盘顺序IO的高速读写特性。
这块比较复杂,我就不太多延伸了,听不懂也没有关系,了解一下就行,一般面试也不会问到这块。
好啦,这就是今天全部的内容,如果你喜欢我的分享,记得点个关注支持一下,我们下期再见。