Mysql索引为什么选择B+树

Mysql索引底层数据结构(B+树)

索引是放到内存中还是在磁盘中?

磁盘,虽然内存的读取速度很快,但是我们还是把索引存放到磁盘上,这样的话,当我们在硬盘上进行查询时,也就产生了磁盘的IO。相比于内存的存取来说,磁盘的IO存取消耗的时间要高的多。但是数据是在磁盘中的,因为放到内存中的话有可能导致数据丢失,另一个原因是内存相对于磁盘来说更加珍贵,不会有太多的内存让我们当数据库来使。所以索引也存储在磁盘中,通过索引来使磁盘IO减少,从而提高效率。

其实在使用B+树作为索引的底层结构之前我们可以考虑一下我们之前学过的数据结构有没有适合作索引的底层结构的。

1、数组

数组的查询是很快的,前提是直到数据的下标,若是不知道下标就没法查询。对于有序数组我们二分查找也是很快的,但是插入数据的时候需要维护这个顺序,需要进行大量数据的移动,所以数组不是很好的选择。

2、链表

链表的查询速度是O(n),速度好像不是很快。

3、哈希表

哈希表是一种数组+链表的结构,它是将 key 通过一个哈希函数计算出一个数字,然后以该数字作为数组的下标,然后将 value 存放到对应下标的数组中。对于不同的 key,在经过哈希函数计算后,可能出现相同的值,这种情况叫做哈希冲突,这时候就意味着同一个数组下标处要存放两个元素了,所以这个时候将数组中的元素变为一个链表,通过链表将这两个元素串联起来。

哈希表对于删除、查找、更新、插入操作,都是先根据 key 计算出一个值,就能定位到数据的目标位置了,时间复杂度都是 O(1),速度特别快。但是我们在使用 MySQL 时,经常会遇到查找某个范围内的数据,例如 between…and、>=、<=等范围查找操作。因为哈希表的所有 key 都会经过哈希函数计算,然后再存放数据,本来可能有序的 key,但经过哈希函数计算出来的值就不是有序的了,所以这个时候,如果要在哈希表中进行范围查找,就只能对整个哈希表进行遍历了,只有符合条件范围的数据,才取出来。因此,从范围查询的场景来看,哈希表也不太适合作为 MySQL 索引的数据结构。

4、二叉树

常用的二叉树有二叉搜索树、AVL 树(平衡树)、红黑树等。

4.1二叉搜索树

对于二叉搜索树而言,它的查找操作的时间复杂度就是树的高度,最理想的情况下,也就是满二叉树的情况下,查找的时间复杂度为 O(logn)。当我们在不停地动态地往树中插入数据、删除数据时,在极端情况下,二叉搜索树可能退化成链表,它的查找时间复杂度就变成了 O(n),性能不够稳定。

4.2平衡二叉树

平衡树是在二叉查找树的基础上,增加了一条限制,左右两个子树的高度差不能超过 1,左右两边相对平衡,因此称之为平衡树。而平衡树在数据动态地删除、插入地过程中,为了维护平衡,避免树退化成链表,因此需要在删除或者插入数据后进行额外的旋转操作,会损耗一定的性能,但整体来讲,它的查找、删除、插入、更新的复杂度均为 O(logn)。它的中序遍历,数据是有序的,因此也适合范围查找。但是它的缺点是,为了维护平衡,它的旋转操作过于复杂。

4.3红黑树

红黑树是一种近似平衡(不完全平衡),结点非黑即红的树,它的树高最高不会超过 2logn,因此查找的时间复杂度为 O(logn),无论是增删改查,它的性能都十分稳定。工程上,很多地方都使用的是红黑树这种数据结构,例如 Java 中的 HashMap、TreeMap 等。

无论是二叉搜索树,还是 AVL 树,亦或是红黑树,它们都是二叉树的一种,特点都是每个结点最多只有两个子结点,如果存储大量数据的话,那么树的高度会非常高。而 MySQL 存储的数据最终是要落地到磁盘的,MySQL 应用程序读取数据时,需要将数据从磁盘先加载到内存后才能继续操作,所以这中间会发生磁盘 IO,而如果树太高,每遍历一层结点时,就需要从磁盘读取一次数据,也就是发生一次 IO,如果数据在树高为 20 的地方,那查找一次数据就得发生 20 次 IO,这对应用程序简直就是灾难性的,耗时太长了。因此二叉树在 MySQL 这种需要存储大量数据的场景下,是不适合当做索引的数据结构的,因为树太高,操作数据时会发生多次磁盘 IO,性能太差。

5、B-Tree 与 B+Tree

既然二叉树因为每个结点最多只有两个子结点,最终在存储大量数据时导致树高太高,因此不适合当做 MySQL 的索引,那么让树的每个结点尽可能多的拥有多个子结点,也就是多叉树,那这样在大量储存数据时,树高就低很多了,而多叉树中典型的例子有 B-Tree 和 B+Tree。

5.1B-Tree

B-Tree 的特点是无论叶子结点和非叶子结点,它都存有索引值和数据;

5.2B+Tree

B+Tree 的特点是只有叶子结点才会存放索引值和数据,非叶子结点只会存放索引值本身。因此对于非叶子结点,一个结点中,B+Tree 存放的索引值数量会远远大于 B-Tree(因为一个结点的空间是有限的,B-Tree 要存放索引+数据,而 B+Tree 只需要存放索引),这样就导致了每个结点中,B+Tree 能向下分出更多的叉,子结点数更多。

那么在要存储同样大小的数据文件的场景下,用 B+Tree 存储,最终树的高度会远远小于用 B-Tree 存储的高度,所以使用 B+Tree 作为 MySQL 索引的数据结构,将来在读取数据时,发生的磁盘 IO 次数会更少,性能更优,因此最终 MySQL 索引的数据结构使用的是 B+Tree。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值