龙空技术网

先简单理解一下Mysql索引底层原理

JAVA小学生 177

前言:

眼前大家对“mysql索引底层”大致比较看重,各位老铁们都需要分析一些“mysql索引底层”的相关知识。那么小编在网络上收集了一些关于“mysql索引底层””的相关内容,希望小伙伴们能喜欢,咱们一起来学习一下吧!

一直想写一篇关于Mysql索引底层实现原理的文章,今天正好有同事问关于Mysql索引的问题。顺便整理一下思路,深层次的理解也不够透彻,就先从一些浅显的原理归纳一下。

创建表

先来看一个建表脚本和insert的脚本。

建表脚本

首先创建一张t1的表,a,b,c,d四个字段都是int类型,e字段是varchar类型。并且a是t1表的主键。这里使用了InnoDB存储引擎。

insert脚本

再来看看插入数据的脚本。这里的插入顺序是无序的。

插入后的记录

插入之后,表中即按照a字段进行了升序排序。所以可以得出结论,利用InnoDB存储引擎在插入数据时,会按照既定的索引(主键默认作为索引)进行排序。这里之所以排序是为了查询的方便,我们知道要想对数据进行查询,一般最先做的就是对数据进行排序,然后再按照既定的查询方法(如:二分法)进行查询。

所以,使用InnoDB存储引擎时,数据插入效率低(因为需要排序),数据查询效率高。

大家也可以试试用其他的存储引擎试试,比如MyISAM。数据结果是按插入的顺序显示的。

建索引

在了解Mysql是如何创建索引之前,先介绍一下Mysql中数据页的概念。

Mysql的数据页结构

以上是Mysql中数据页的结构,这里介绍组成数据页的几个关键结构。

File Header:其中包含了FIL_PAGE_PREV和FIL_PAGE_NEXT,这两个属性分别指向上一页和下一页的指针。所以,这里可以把数据页理解成是一条双向链表。

User Records:这里存放实际的数据行记录。

Page Directory:页目录,记录与二叉查找相关的信息。

好了,下面根据我们创建的t1表,看一下每页都存放了哪些内容。

根据上图可以看到:现在把8条记录分成两个页(当然,每个页的记录条数根据记录大小而定。默认Mysql的数据页大小是16384b,也就是16kb)。页号分别是1和2。

其中类似1_134a这样的就是记录,用下划线区分主键和非主键的列。每页的左侧两个方框中就是上面提到的Page Directory,也就是页的目录。每个页目录都可以代表多条记录(这里代表两条记录),而目录中存放的就是所有记录中主键最小的值。也就是页目录1可指向主键是1和2的两条记录,页目录中存的值是1_134a这条记录的主键。

并且两个页互相指向,就是上面提到的FIL_PAGE_PREV和FIL_PAGE_NEXT。

这就是Mysql中主键索引的雏形。其实这就是一棵B+树,在Mysql中有两种索引方式,一种是BTREE,另一种是HASH。常用的就是BTREE,也就是一棵B+树。

下面给出主键索引的B+树结构图,这里假设每页只能存两条记录:

主键索引BTREE

有了这个BTREE,那么看一下Mysql是怎么利用这个主键索引树去做查询功能的。

select * from t1 where a = 3

1、 在树根用3去比较,发现5比3大,所以要沿着左侧往下找;

2、 到第二层直接找到了3指向的页,沿着箭头方向往下找。

3、 到第三层,叶子节点在查找,直接找到了3这个页,则直接找到了数据值。

以上查找过程用了3步。试想一下,如果直接在叶子节点从左到右依次查找的话也是3步就能找到。但如果where条件中是a = 8呢?直接从叶子节点从左到右需要找8次。而利用这个主键索引的BTREE,只需要3次即可。所以索引起了作用,优化了查询。

再建索引

上面介绍的是主键索引,也就是如果给表中某列标识为主键,则该列就自动创建了索引。那么如果非主键列创建索引会是什么样的结构呢?先来看一下这条语句:

创建辅助索引

这里给b,c两列创建了索引,叫做辅助索引。Mysql中有主键索引和辅助索引两类索引。

注:Mysql5.8版本支持给索引的排序。即:create index ind_t1_bc on t1(d desc, c asc)。低版本的默认都是升序asc。

给b,c两列创建的索引是如何排序的呢?这里类似字符串的排序规则,先比较第一个数再比较第二个数。比如:主键是1的记录bc字段拼接后是13,主键是2的记录bc字段拼接后是72。所以排序就是1在2前,下面看下创建完辅助索引后,Mysql会创建一棵以下的BTREE。各位可以根据数据看一下,按照bc排序后的顺序就是叶子节点从左到右的顺序。叶子节点中白色的数字就是这条记录的主键值。

辅助索引BTREE

执行explain select * from t1 where b = 3 and c = 5。

这里用到了inx_t1_bc这个索引进行的查找。

如果上面的查询语句换成explain select * from b = 3。会是什么效果呢?

如果上面的查询语句换成explain select * from c = 5。会是什么效果呢?

可以得出结论,bc的联合索引中,如果b参与查询,索引生效,只有c参与查询,索引不生效。也就是条件中(1*)生效,而(*1)不生效。这也就是为什么在查询中不建议使用like关键字的原因了,因为需要全表扫描。

至此,介绍了Mysql的InnoDB存储引擎中根据索引创建的BTREE结构,包含了主键索引和辅助索引。大家以后在建索引的时候可以参考。

关注作者+转发,

然后私信关键词(springcloud)就能免费领取一套springcloud视频教程

标签: #mysql索引底层