前言:大部分人都知道,MySQL底层使用的是B+树这个数据结构,但是你们知道为什么是B+树呢?为什么不是哈希索引,为什么不是平衡二叉树(AVL,甚至红黑树)呢?或者说为什么不是B树呢?这里我就带大家一步一步来解释为什么是B+树,废话不多说,现在开始~

为什么不是Hash索引?

首先这里说的是面试中常问到的,为什么不是Hash索引?因为对应hash值,它是一个无序的这么一个值(底层计算就不解释了,位运算等~),既然是无序,那么就有一个致命的缺陷,那就是不能进行范围查找。因为数据库操作中常常需要进行范围的查找的过程,再比如你如果需要索引进行排序操作的话,不能使用哈希值来进行排序,因为它本来就是一个无序的值。这里就解释了uuid为什么不能当作数据库的主键索引,随机范围太大,而且无序,再加上本身是一个字符串,存储的字节数也需要增多,存储受限。还有一些小问题,那就是哈希冲突,比如我的值不同,但是我的哈希值是相同的,那么查找速度也会跟着变慢了,一个一个比对,相当于是遍历整张表。这里就解释了为什么MySQL底层不能使用哈希索引的方式。

为什么不是平衡二叉树(AVL Tree)

对1~10这个数进行模拟插入到AVL Tree中演示为例,我们可以发现二叉树的高度为3,因此理论上假如二叉树的节点在硬盘中存放(一般二叉树都存储在内存中),需要进行IO次数为四次才能访问到查找到10,随着数量的越来越多。

1.这个数据结构的致命缺点也随之显性,没错,那就是频繁的IO,我们都知道IO的访问时间是非常耗时的,需要操控磁头等。

2.还有一个致命的缺点就是范围查找会随着这颗树的高度越来越长时间,比如我们这里需要查找到大于5的全部节点,那么我们首先需要定位到5,需要三次查找,然后我们需要回旋查找,依此是6,7,再回到8,再9,再10,这样就把所有大于5的数据都拿出来了,假如大于5的数非常非常多,可想而知~时间复杂度得多恐怖!!

int mysql 底层 mysql底层是什么树_链表

为什么不是B树

这里我们以三阶B树来演示,实际上在数据库中有几百阶的很正常。还是和AVL树一样,还是以插入1~10个数为例,这里我们可以很明显的看出高度比平衡二叉树低一些,数量越多B树的高度的层数降低的越明显。这里看似是比AVL二叉树的IO次数降低了是吧。
但是还有一个致命的缺点,它并没有解决范围查找中回旋查找的效率低下问题,比如我这里还是以查找大于5的全部数据为例,这里同样需要先找到5这个节点,然后回旋依此找到6,7,8,9,10,因此B树还是没有解决范围查找中回旋查找的问题,但是B树解决了IO次数降低的问题,因为B树中每一个节点存放了多个节点信息,这里一次IO就能将多个节点同时读入到内存的目的。
可能有的小伙伴会说为什么不将平衡二叉树的多层同时加载内存呀,这样不就降低的IO吗,你傻呀,节点的地址都是随机的,你能一次性都找到他们的地址再加载进吗,就算你加载进了也访问的IO不止一次吧(差不多是找一个节点一次IO),我们这里是以一次IO为前提的哟,别犯傻!

int mysql 底层 mysql底层是什么树_mysql_02

那这个范围查找中的回旋查找问题到底能不能解决呢?

这里就需要引出我们的主角了,B+树!

没错,它彻彻底底的解决了范围查找回旋的问题,它是怎么解决的呢?

这里我还是以插入1~10为例,也是三阶B+树,这里我们可以惊奇的发现,B+树的叶子节点有一个单向链表!它把你所有的树进行了一个链表的排序,我们说B+树解决了范围回旋查找的问题,没错,就是靠这个单项链表保证了有序 【这里我们可以联想到java的LinkedHashMap,也是有一个单向(双向)链表来保证底层数据顺序插入的问题】

这里简单说一下B+树的结构,首先非叶子节点,它是存放索引(key)的,【索引就是指一个节点的标记,你可以理解为hash一样】,不存放value。而叶子节点即存放key【索引】,也存放value,这里说的value指的是真正数据的地址 【一般数据的索引和数据的地址存放在一起(为一张表),而真正的数据是单独存放在另一张表中的】

int mysql 底层 mysql底层是什么树_int mysql 底层_03


辅助网站:https://www.cs.usfca.edu/~galles/visualization/