字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

232 篇文章 5 订阅
23 篇文章 0 订阅

本身也想写点关于MySQL基础的东西,但是,网上一搜,各大论坛真的有好多,正好最近好多朋友在面试字节的时候,被问到底层算法的东西,然后被询问了一波,那我们就来看一下mysql底层所能涉及的算法,都研究明白了之后,是不是就不怕面试官扩展开来问mysql了呀

文章首发个人公众号:Java架构师联盟,每日更新技术好文

运行流程

关于mysql的内部运行流程,这里不做过多的解释,通过下面这张图,我给大家讲解一下

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

注意:不同的存储引擎,数据文件和索引文件存放的位置是不同的,因此有了分类:

聚簇索引:数据和文件放在一起: innodb

.frm:存放的是表结构

.ibd:存放数据文件和索引文件

注意: mysql的innodb存储引擎默认情况下会把所有的数据文件放到表空间中,不会为每一个单独的表保存一份数据文件,如果需要将每一个表单独使用文件保存,设置如下属性: set global innodb_file_per_table=on;

非聚簇索引:数据和索引单独一个文件:MylSAM

.frm:存放表结构

.MYI:存放索引数据.MYD:存放实际数据


那mysql的索引数据结构是什么呢?我们来看一下

哈希表可以完成索引的存储,每次在添加索引的时候需要计算指定列的hash值,取模运算后计算出下标,将元素插入下标位置即可,适合场景:等值查询

但是如果表中的数据是无序数据(范围查找的时候比较浪费时间,需要挨个进行遍历操作),而在企业中多数的查询是范围查询,所以此时hash表不是特别合适,并且hash表在使用的时候,需要将全部的数据加载到内存,比较耗费内存的空间,也不是很合适

所以我们需要进行更换,首先想到的是什么----树

在树的结构中,左子树必须小于根节点,右子树必须大于根节点,如果是多叉树的话,从

左到右是有序,所以应该是可以的,我们来看一下(这也是在面试的过程中经常被询问的问题)

先看一下树都包含那些内容

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

排除前面几个,最适合的就是AVL树以及红黑树,我们分开查看一下

首先是AVL树

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

AVL树是一颗严格意义上的平衡树,最高子树跟最低子树高度之差不能超过1,因此在进行元素插入的时候,会进行1到N次的旋转,严重影响插入的性能,pass

其次是红黑树

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

之前的时候写过一篇红黑树的文章,有兴趣的朋友可以详细地看一下:快进收藏吃灰!字节跳动大佬用最通俗方法讲明白了红黑树算法

红黑树是基于AVL树的一个升级,损失了部分查询的性能,来提升插入的性能,在红黑树中最低子树跟最高子树之差小于2倍即可,在插入的时候,不需要进行N多次的旋转操作,而且还加入了变色的特性,来满足插入和查询性能的平衡

但是我还是要告诉你,pass,为什么?因为二叉树及其N多的变种都不能支撑索引,原因是树的深度无法控制或者插入数据的性能比较低

那既然寻常的二叉树不太好用,但是又想用树这个结构,那换个思路呢?B树怎么样?看一下

B树特点:

1、所有键值分布在整棵树中

2、搜索有可能在非叶子结点结束,在关键字全集内做一次查找,性能逼近二分查找

3、每个节点最多拥有m个子树

4、根节点至少有2棵树

5、分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点)

6、所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列

一张图展示一下

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

解释说明

每个节点占用一个磁盘块,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指十存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为16和34,P1指|指向的子树的数据范围为小于16,P2指针指向的子树的数据范围为16~34,P3指针指向的子树的数据范围为大于34。

查找关键字过程:

1、根据根节点找到磁盘块1,读入内存。【磁盘V/О操作第1次】

2、比较关键字28在区间(16.34),找到磁盘块1的指针P2。

3、根据P2指针找到磁盘块3,读入内存。【磁盘I/O操作第⒉次】

4、比较关键字28在区间(2531),找到磁盘块3的指针P2。

5、根据P2指针|找到脑盘块8,读入内存。[磁盘|/O操作第3次】

6、在磁盘块8中的关键字列表中找到关键字28。

缺点:

1、每个节点都有key,同时也包含data,而每个页存储空间是有限的,如果data比较大的话会导致每个节点存储的key数量变小

2、当存储的数据量很大的时候会导致深度较大,增大查询时磁盘io次数,进而影响查询性能

那既然还是会影响mysql的查询性能,那mysql的索引数据结构是什么样子的呢?我们优化一下B树——B+Tree是在BTree的基础之上做的—种优化,变化如下:

1、B+Tree每个节点可以包含更多的节点,这个做的原因有两个,第一个原因是为了降低树的高度,第二个原因是将数据范围变为多个区间,区间越多,数据检索越快

2、非叶子节点存储key ,叶子节点存储key和数据

3、叶子节点两两指针相互连接(符合磁盘的预读特性),顺序查询性能更高

这么说可能有点抽象,那我给大家通过一张图展示一下

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

注意:在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找和分页查找,另一种是从根节点开始,进行随机查找。

那B+Tree如何放置数据呢?

mysql InnoDB–B+Tree,叶子节点直接放置数据

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现

注意:

1、InnoDB是通过B+Tree结构对主键创建索引,然后叶子节点中存储记录,如果没有主键,那么会选择唯一键,如果没有唯一健,那么会生成一个6字节的row_id来作为主健

2、如果创建索引的键是其他字段,那么在叶子节点中存储的是该记录的主键,然后再通过主键索引找到对应的记录,叫做回表

mysql MylSAM–B+Tree

对于MyISAM的查找顺序,我从网上找到了这样的一张图,我个人感觉看起来是比较直观的

假设我们的数据不是按照之前的顺序插入的,而是按照图中的是顺序插入表,可以看到MyISAM引擎下,B+树叶子节点中包含的是数据记录的地址(可以简单理解为“行号”),而MyISAM的辅助索引在结构上和主索引没有本质的区别,同样其叶子节点也包含了数据记录的地址

字节跳动内部授课课件:附图讲解MySQL底层索引结构算法实现


到这里,基本对于数据库底层索引结构的内容就讲完了,其实看一下大多数也是算法和数据机构的问题,这里也是展示了数据结构对于你想往上走的重要性,计算机就是这样,相互之间结合是很重要的,所以学习一定要成体系的学习,融汇贯通才是最重要的

不知道今天的内容大家有没有什么收获呀?哈哈哈哈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值