mysql的explain详解

提示:explain详解、explain中index和ref的区别?

文章目录

  • 前言
  • 一、mysql索引的底层结构
    • 2.1主键索引
    • 2.2非主键索引
  • 二、explain详解
    • 2.1、id
    • 2.2、select_type
    • 2.3、table
    • 2.4.partitions
    • 2.5.type
      • 2.5.1、NULL
      • 2.5.2、system、const。
      • 2.5.3、eq_ref
      • 2.5.4、ref
      • 2.5.5、range
      • 2.5.6、index
      • 2.5.7、all
    • 2.6.possible_keys
    • 2.7.key
    • 2.8.key_len
    • 2.9.ref
    • 2.10.row
    • 2.11.extra
      • 2.11.1、Using index
      • 2.11.2、Using where
      • 2.11.3、Using index condition
      • 2.11.4、Using temporary
      • 2.11.5、Using filesort
      • 2.11.6、Select tables optimized away
  • 总结


前言

mysql中的explain的每个字段的解释。本人水平有限,如有误导,欢迎斧正,一起学习,共同进步!


一、mysql索引的底层结构

这里直接放两张图吧,拿innodb来说,他的普通索引和主键索引的区别。其实关于索引,网上的定义很多,一级索引、二级索引、聚合索引、聚集索引、普通索引…大家可能有点晕。简单的说:一级索引=主键索引=聚集索引。二级索引=普通索引=非聚集索引。其实博主的另一篇博客写的更加详细,大家感兴趣的话,可以去看看另一篇。

2.1主键索引

主键索引的叶子节点,存储的是当前数据行的全部字段的内容。innoDB,只有一个主键(聚簇)索引,如果你有主键,则主键去组织这个B+Tree的结构,如果你没自增主键,则mysql会自己维护一个隐藏列去当主键去维护B+Tree的结构。

2.2非主键索引

非主键索引的叶子节点,存储的是当前数据行的,主键索引的磁盘地址。这就是,为什么非主键索引需要回表的原因,因为他不包含全部的字段内容。当然,如果查询方式为覆盖索引的话,也不需要回表了
mysql的explain详解_第1张图片

二、explain详解

总的来说,explain中,比较重要的几个参数是:type、rows、key、possible_key、extra。绝大多数情况下,你甚至可以只看type、rows。rows是mysql本次查询可能要查询的行数,这个值越小越好。type的查询效率从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL

2.1、id

id列的编号是select的序号,有几个select就有几个id,并且id的顺序是按select出现的顺序增长的。
id不一定是唯一的,id列越大执行优先级越高,id相同则从上往下执行id为null最后执行

2.2、select_type

取值范围如下:

  • simple:简单查询。查询不包含子查询和union
  • primary: 复杂查询中最外层的select
  • subquery:包含在select中的子查询(在select不在from子句)。下图中的actor表
  • derived:包含在from子句中的子查询。mysql会将结果存入一个临时表,也称为派生表。下图中的user表。

mysql的explain详解_第2张图片

2.3、table

table就是查的哪张表,没啥可说的。

2.4.partitions

partitions是分区的意思。一般有分区的时候,有这个。相对比较少见。

2.5.type

type列比较关键。上面咱们也说了,他的效率从最优到最差分别为:system > const > eq_ref > ref > range > index > ALL。

2.5.1、NULL

NULL:mysql能在优化阶段分解查询语句,在执行阶段不在访问表或者语句。例如:在索引列中选取最小值,可以单独去查索引完成,不需要再执行时访问表。
mysql的explain详解_第3张图片

2.5.2、system、const。

const:mysql能对查询的结果进行优化,并将其转化为一个常量(可以看做是show warning的结果)。一般是用primary key 或者unique key的所有列与常数比较时,所以表最多有一个匹配行,读取一次,速度比较快。(一般是主键或者唯一索引的时候,会是const)
system:system是const的特例。表里只有一条元素匹配时,为system。(我理解的是,表里有多条记录,通过唯一值查时是const;整个表里就一条记录,通过唯一值查时,是system)要查询的结果集,本身就只有一行记录,为system。
mysql的explain详解_第4张图片

2.5.3、eq_ref

eq_ref:primary key 或者unique key索引的所有部分被连接使用,最多只会返回一条符合条件的记录。这可能是在const以外最好的连接类型了。简单的select查询不会出现这种type。(简单的说,关联查询条件是主键或者唯一索引,就是这种类型)
mysql的explain详解_第5张图片

2.5.4、ref

ref:不是使用的唯一索引,而是使用的普通索引或者唯一索引的部分前缀。索引要和某个值比较,可能会找到多个记录。(走索引了,但是走的普通索引,不是主键索引,就是ref)
mysql的explain详解_第6张图片

2.5.5、range

range: 范围扫描。通常出现在 in()、between、>、<、>=等操作。使用一个索引来给定范围的行。普通索引、主键索引都行。(也走索引了,但是是范围,肯定没前面的几种快)
mysql的explain详解_第7张图片

2.5.6、index

index:扫描全索引就能拿到结果。一般是扫描某个二级索引,这种扫描不会从索引树根节点开始快速查找。而是直接对二级索引的叶子节点遍历和扫描,速度还是比较慢的,这种查询一般为使用覆盖索引,二级索引一般比较小,所以这种通常比all快一些。
知识点:为什么select * from ,但是会走索引呢?key = idx_name 。因为二级索引会存索引,还会存这个索引对应的一级索引。而这个user表一共就id、name俩字段。name是二级索引,name下的叶子节点存的是主键索引(也就是id),也就是说,只扫描二级索引就能查到全部的数据了,那肯定就走的二级索引。前面“知识点”这段话,就是覆盖索引的原理
mysql的explain详解_第8张图片

2.5.7、all

all:全表扫描。他是根据主键索引,去挨着扫描,全部的叶子节点。听起来跟index比较像,只不过index是扫描全部的普通索引的叶子节点,而all是扫描全部的主键索引的叶子节点。(因为主键索引的叶子节点有全部的行数据。)
mysql的explain详解_第9张图片

2.6.possible_keys

possible_keys:这个执行过程中,可能会用到的索引。(显示的是,这个查询,可能会用到的哪些索引。比如说,mysql分析的时候,觉得你走a索引会快。容纳后possible_key就是a,但是真正执行的时候,mysql发现不用这个索引,全表可能更快,然后key就是空了。就是分析的possible_keys有索引,实际key没走索引)。mysql认为可能会走的索引(实际可能没走)。

2.7.key

key: 这条语句,执行过程中,真正用到的索引。(显示的是mysql实际采用哪个索引来优化对该表的访问)。mysql在本次查询中,真正有没有走索引。possible_keys是可能会用到的索引,key是真正有没有走索引。

如果你的explain是这种情况:

  • possible_keys有列,而 key
    显示null:这是因为,mysql认为,走了索引的查询,可能还没全表扫描执行的快,因此就没走索引,直接全表扫描了。(可能的场景有:表中的数据不多)
  • prossible_keys没列,这时可能需要加索引来优化你的查询

2.8.key_len

key_len:显示的是,mysql在索引里,使用的字节数。可以判断出来,具体使用了索引中的哪些列。比如你的联合索引,俩个int类型,第一个字段是int占了4字节,第二个字段也是int,也占了4字节,如果key_len是4的话,说明使用了联合索引的前一个字段,如果key_len是8的话,说明使用了联合索引的俩字段。
之所以是5,是因为int占了4个字节;字段允许为null,需要1个字节去记录是否为空,所以是5字节。
mysql的explain详解_第10张图片
mysql的explain详解_第11张图片
key_len的计算规则
mysql的explain详解_第12张图片

2.9.ref

ref:在key列记录的索引中,表查找值所用到的列或常量,常见的有:const、 字段名(如 film.id)
mysql的explain详解_第13张图片
mysql的explain详解_第14张图片

2.10.row

row:这个行数是mysql预估要读取并检测的行数,注意这个不是结果集里的行数。是估计要扫描多少行,才能拿到结果。越小越好,越小查的越快

2.11.extra

extra:这一列是展示的额外信息。一共可能有几十种,下面列举了一些比较常用的。(大概了解一下就行)

2.11.1、Using index

Using index:使用覆盖索引。意思就是说,在这次查询中,我只查索引(一般是指普通索引),就能查到全部的结果集(因为普通索引的叶子节点是主键索引),并不需要再根据主键索引去回表,查其他数据。
有 Using index 代表不会回表。比extra为空时(会回表)的效率高。
mysql的explain详解_第15张图片

2.11.2、Using where

Using where:使用 where 语句来处理结果,并且查询的列未被索引覆盖。就是说,salary不是索引,就是普通的查询。
mysql的explain详解_第16张图片

2.11.3、Using index condition

Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围;
在这里插入图片描述

2.11.4、Using temporary

Using temporary: 是走了临时表的,比如说你是distinct name。name不是索引的话,mysql就会先把数据搂出来,搂出来以后,去放一个临时表,然后在临时表中,一行一行的,逐行去重,去完重以后,再从临时表中拿数据,去展示。
因为他是索引,而索引是有序的,mysql在扫描索引的时候,一看这俩一样,就直接去重了,所以不在需要临时表去去重了,所以更快一些。
mysql的explain详解_第17张图片
mysql的explain详解_第18张图片

2.11.5、Using filesort

将用外部排序而不是索引排序,数据较小时从内存排序,否则需要在磁盘完成排序。这种情况下一般也是要考虑使用索引来优化的。
在这里插入图片描述

2.11.6、Select tables optimized away

使用某些聚合函数(比如 max、min)来访问存在索引的某个字段、
在这里插入图片描述


总结

explain可以极大的方便我们排查问题,因此,熟悉掌握explain对于后端开发来说是很有必要的。

你可能感兴趣的:(Java,mysql,后端,sql)