MySQL索引为什么选择B+树作为数据结构?

如果没有使用某种数据结构,mysql是如何查找的

我们首先明确mysql只是一个软件的概念,它的作用是在我们存储数据的时候建立起一个关系并且方便我们对这些数据进行处理。
所以我们的数据根据mysql引擎的不同,存放的位置也有区别,但是我们常用的innodb是会把数据落到磁盘的。那么我们的mysql去查询数据也是要先从磁盘中读取数据到内存中再去查找。
那么我们要研究的就是mysql通过什么方式能够做到最少次数的从磁盘上读取数据到内存以及最快的从在内存里的数据里找到我们想要的数据对吧。那我们就会考虑到一个问题:如果什么数据结构都不使用,那mysql就得从整个数据的头开始一点一点的将数据读到内存,再从内存里的数据一条一条的查找。因为我们不聪明,只能用这种蠢方法死找,所以如果要找的数据在第一条还好,一下子就找到了,但是如果在最后一条,那不得从早找到晚,夸张了,但是也差不多了。
所以我们就要把这些数据建立起某种数据结构来方便我们进行筛选查找。

如何选妃(数据结构

我们都知道数据结构有数组、链表、哈希表、树、图、堆等等,其中适合搜索的就哈希表和树。
memory存储引擎就是基于哈希的,而innodb也是有一个自适应哈希索引的,而且学过HashMap的都知道在哈希表中查找数据是很快的,但是哈希表有个致命的缺点——不能进行范围查询。但是我们经常要查询一些范围查询,比如查找年龄低于40岁的教师、查找薪资大于10000小于15000的员工等等,而且要用哈希表的话每次都要把所有的数据都放到内存里,是很消耗内存空间的,于是我们将哈希表这种数据结构pass掉。
接着我们看树。
树的种类就多了啊,二叉查找树、二叉平衡树、红黑树、B树、B+树,那我们怎么从中选出最合适的呢?
我们先看二叉查找树:
二叉树1
二叉树2

观察一下这两棵二叉查找树,你就会发现如果插入的结点一直是递增的,那不是就退化成链表了吗,那我还不如用哈希表呢。为了解决这个问题,就有了二叉平衡树,二叉平衡树规定左右结点的层数之差不能大于1,看下图:
二叉平衡树
这可就比二叉查找树的性能不晓得提高了多少,但是如果结点一多,层数也就越来越多了,我们算一笔帐,mysql每次读取一页,也就是16kb,我们假设一个结点(数据+指针)占1kb,那么一页能存储16个结点也就是16条数据对吧,那我们要是要找的结点在特别后面了,比如一共有160条数据,二叉树只有两个分支,那么如果我们要找第160条数据可能要进行4次IO,不行还是划不来,红黑树同理。

但是红黑树肯定要比二叉平衡树要好一丢丢的,好在哪呢,你看二叉平衡树动不动就要进行左旋右旋的来保持平衡,因为它两边之差不能超过1,那这样的话如果写进去的频率要远高于读出来的频率呢,那不就得不偿失了,但是红黑树只要求两边之差不能超过2,就稍平衡了写入和读取

那既然两个分支的查找效率低了,那多个分支呢,于是引申出了B树。什么是B树就直接去百度一下就好了,它是指针和数据放在一起的多叉树,如下图:
度为3的B树
那么我们可以再计算一下,假设每个结点占1kb,那么每页能存储16个结点,同样是160个结点找第160个我们只需要进行2次IO就可以查找到目标数据,跟二叉平衡树相比可整整快了一倍。但是这样算的话3层B树只能存储16✖16✖16=4096的数据,会不会太少了一点呢,要知道如果数据多的话能到几百万条数据,什么,你说再多加几层?那可不跟二叉平衡树差不多了吗。那该怎么办呢,你看B树的结点的结构是怎么样的,数据和指针在一起了对吧,那如果我们把指针放在非叶子节点,数据放在叶子节点呢,那是不是跟开花一样数据能存的多很多了,于是就有了B+树。
度为3的B+树
如图,前两层是主键+指针,最后一层是数据,这样的话假设主键是6bit,索引8bit,数据1kb,那么一页就能存储(16✖1024)/(6+8)约等于1170个非叶子节点,那么三层B+树的话能存储1170✖1170✖16=2190万条数据,2190w可远大于4096,而且在B+树的叶子节点上还设置了一个双向循环链表的结构,查询效率杠杠滴!

以上,就是为什么选择B+树这种数据结构的原因了,如有错误,欢迎指正!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值