MySQL进阶之路(十六)—— 透彻理解InnoDB中的B+树以及回表操作

透彻理解InnoDB中的B+树及回表操作

一、概述

​ 在上一篇文章中详细的介绍了记录和数据页在磁盘上的结构,没有看过的可以点这里去快速把知识补上,今天将在此基础之上以一个更大的视角去探究一下B+树的结构。

二、透彻理解B+树之前必需知道的点

​ 1、首先,记录都是存储在数据页中的,并且是通过next指针构成了单链表的结构

​ 2、数据页与数据页之间是以通过两个指针组成了一个双向链表,每个数据页大小默认16k

​ 3、每个数据页都有一个自己的页目录,用于根据索引列在页内进行二分查找

​ 4、上一篇文章说过,数据页也分很多种类型,如:FIL_PAGE_INDEX:叶子节点页、FIL_PAGE_INODE:索引节点页

三、为什么会用B+树来存储?

​ 首先,InnoDB引擎是帮助我们管理数据的,其中肯定有查询操作,而且对于我们程序猿来说,要查找的是我们想要的某些记录,并不是数据页。那么问题来了,如果只有一个数据页那就好办,可以直接利用数据页目录进行二分查找或者直接通过遍历的方式来查找。因为数据页的大小是有限制的,默认16k,当数据量变大的时候,一个数据页肯定是不够用的,此时可能会有上千上万个数据页,这个时候该怎么去查找我们想要找的记录呢?

​ 从步骤上来说,我们肯定是需要先找到记录在哪一个数据页中,然后再到这个数据页中去寻找我们想要的记录。这个道理很简单,就像是你要去某个地方去旅游,你肯定是要先坐火车到它所在的省/市,然后再到达它所在的区/县,然后才能找到。因为没有一条专门的路可以从你家直通你想去的地方,那样花费的代价真的太大了!

​ InnoDB的做法就是先定位到数据页,问题又来了,那么应该如何去组织数据页来实现快速查找呢?常用的方法有在有序的数据中进行二分查找,但是数组有个致命的问题——无法扩容。还有利用二叉搜索树(比如AVL树或者红黑树)来进行查询数据,也很快。但是对于数据库这种场景缺点也很明显——插入操作可能伴随旋转操作并且可能递归到根节点,当数据量比较大的时候,是很影响性能的,并且树的高度也会很高,不利于查找。当然,还有其他的,比如跳表(Redis中有用到的)等这里就不展开来说了。

​ 总之,对于数据库这种场景,在各种数据结构中选来选去,最后发现B树是最合适的,因为它有如下几个优点:

​ 1、树的高度很低(正因为如此,树的高度每增加一层,数据量可能是指数级的增加)

​ 2、插入/删除数据时维护的开销比较小

​ 3、由于数据页之间可以组一个双向链表,可以在叶子节点之间进行横线的查找,因此这种是经典的B树中没有的,所以也被叫做B+树

四、B+树到底长什么样?

请添加图片描述

​ 此时假设id作为索引,因为在每个叶子节点内,记录都是按照索引的顺序排列的,正因为如此,索引节点中保存的是最小id以及对应的页号,我们在查询数据的时候就可以根据每个叶子节点中索引的最小值来判断我们要查找的数据在那一个数据页内,相信这一点大家应该很好理解。

​ 随着数据页越来越多,索引页肯定也会越来越多,那么索引页之间是如何查找的呢?其实道理是一样的!

请添加图片描述

​ 再往上一层的索引节点保存的就是下层索引节点的最小id以及索引节点的页号。现在举一个例子,我现在要查询id=17的记录,那么从根结点出发,首先会找到页号为8的索引节点,然后再再到页号为13的节点,发现是叶子节点后,然后再根据数据页目录中的目录槽进行二分查找。就是这样一个流程

五、那回表查询是什么样的操作?

​ 在数据库中每建立一个索引,就会生成一个B+树,上面那个例子是根据id这个主键字段建立的B+树,叶子节点保存的是完整的数据(所有字段都有),正是因为索引和数据被曝存在同一个B+树中,所以这种主键索引也被称为聚簇索引,对于非主键字段建立的索引也被称为二级索引,因为用二级索引所构成的B+树的叶子节点保存的其实并不是真正要找的记录,而是这个要找的记录的主键。所以,需要根据在二级索引找到的主键,回到聚簇索引中再查找一遍,这种操作就是所谓的回表查询

六、小结

​ 本篇文章介绍了B+树的结构,算是之前文章中所介绍的零碎知识点的集合,通过本篇文章对B+的介绍,相信对前面的概念的理解会更透彻,在理解了那些之后,所谓的回表查询等这些名词都可以顾名思义。

​ 以上就是本篇文章的全部内容了,如果有所的话,可以点个赞支持一下,如果内容有的地方有问题或者不足,欢迎评论指出,共同进步!

猜你喜欢

转载自blog.csdn.net/weixin_44829930/article/details/120923362