0
点赞
收藏
分享

微信扫一扫

Explain执行计划详解

陆佃 2023-01-19 阅读 130


文章目录

  • ​​1、概述​​
  • ​​2、作用​​
  • ​​3、字段详解​​
  • ​​3.1、id​​
  • ​​3.2、select_type​​
  • ​​3.3、table​​
  • ​​3.4、partitions​​
  • ​​3.5、type​​
  • ​​3.6、possible_keys​​
  • ​​3.7、key​​
  • ​​3.8、key_len​​
  • ​​3.9、ref​​
  • ​​3.10、rows​​
  • ​​3.11、filtered​​
  • ​​3.12、Extra​​


我的MySQL版本为5.7,不同版本结果可能略有差异

官方文档地址:​​https://dev.mysql.com/doc/refman/5.7/en/explain-output.html​​


1、概述

用 EXPLAIN 关键字可以模拟优化器执行 SQL 查询语句,从而知道 MySQL 是如何处理你的 SQL 语句的。分 析你的查询语句或是表结构的性能瓶颈。

使用方式:Explain + SQL语句

Explain执行计划详解_字段


2、作用

  1. SQL执行时,表的读取顺序
  2. 数据读取操作的操作类型
  3. 哪些索引能够被使用的,哪些索引是真实被使用的
  4. 表与表之间的引用关系
  5. 每张表有多少行能被优化器优化


3、字段详解

3.1、id

select查询的序列号,包含一组数字,表示查询中执行select语句或者操作表的顺序。



id大小相同,执行顺序由上至下

Explain执行计划详解_子查询_02


当执行结果的id相同时,表示MySQL在分析执行我们的SQL语句时,其执行顺序为由上至下。即例子中,先执行表e的操作,再执行表d的操作。


id大小不同,id值越大优先级越高,越先执行

Explain执行计划详解_字段_03


当执行结果的id不同时,id值越大,执行的优先级越高。即例子中,会先执行表d的操作,然后再去执行表e的操作。


id大小既有相同,又有不同。规则同上

Explain执行计划详解_MySQL_04


在前面两个的基础上,这个也就不难理解了。先执行表t_tag的操作,然后执行表e的操作,最后是表d的操作。


3.2、select_type

查询的类型:主要用于区分此次的查询,属于什么类型,普通查询?子查询?嵌套查询?



常见的属性值,及其含义

  1. SIMPLE:简单的select查询,查询中不包含子查询或者union;
  2. PRIMARY:查询中若包含任何复杂的子部分,最外层查询则会被标记为primary;
  3. SUBQUERY:在select或者where列表中包含了子查询;
  4. DERIVED:在from列表中包含的子查询被标记为derived(衍生),MySQL会递归执行这些子查询,把结果放在临时表中;
  5. UNION:若第二个select出现在union之后,则会被标记为union;若union包含在from子句的子查询中,外层select将被标记为:derived;
  6. UNION RESULT:从union表获取结果的select
  7. DEPENDENT SUBQUERY:
  8. DEPENDENT UNION:


各类型说明

PRIMARYSUBQUERYSIMPLE

Explain执行计划详解_子查询_05

  • e表:我们可以发现,在where条件后面,使用了e表的deptId字段进行子查询。同时,表e所在的位置为嵌套的最外层,即查询类型完全符合primary的规则,所以类型为primary(如果没有where后面的条件过滤,该次查询的类型就是simple
  • d表:subquery与primary的主要区别为,在都含有子查询的基础上,观察该表所处的位置。如果是最外层就是primary,否则就是subquery。此处我们的d表为内嵌在e表的子查询中,符合subquery的规则。


DERIVEDUNIONUNION RESULT

Explain执行计划详解_MySQL_06

补充:上面的SQL查询也是MySQL的7种经典连接之一,如下图:

Explain执行计划详解_MySQL_07

  • d2、e2表:由前文的id大小可知,最开始的两次表操作为操作表d2,再操作表e2。我们发现该表的查询位置位于union关键字之后,所以它对应的查找类型为union
  • d、e表:derived表示临时表,这两个表位于from关键字之后。d表和e表都在from关键字后面,即对于from括号后面的数据集,我们可以将他想象成一个临时表,所以它对应的查找类型也就是derived

小插曲:本人MySQL版本5.7,网上找资料的时候,它们很多人在第一种情况时就能出现derived查找类型。但是我测试了好久都不行(图1),但如果对后面的临时表进行了相关的操作(图2 3),就会出现derived关键字的查找类型。网上相关博客的记录都没有说明MySQL的版本,所以我大胆的假设一下,在MySQL5.7,对derived临时表的出现进行了优化

Explain执行计划详解_MySQL_08


  • <derived2>表:该表为临时表,id最小为1,即表示该SQL的最后一步操作。最后一步操作,由于该查询包含了复杂的子句,注定其查询条件只能是一个primary
  • <union2,3>表:此次操作为连接id为2和3的结果集。所以查找的类型为union result

Explain执行计划详解_字段_09


3.3、table

该列表示此次操作的对象是哪一个表。


3.4、partitions

如果查询是基于分区表的话,会显示对应的分区信息。如果不是分区表,比如我们这里,它就是null。


3.5、type

此次查询,使用了什么类型

常见属性值,及其含义

  1. ALL:Full Table Scan,遍历全表用于查找匹配的行。
  2. INDEX:Full Index Scan,index和all的区别为index类型只遍历索引树(可以理解为只查询索引列),这通常比all来的快。因为索引文件通常比数据文件小。
  3. RANGE:只检索给定范围的行,使用一个索引来选择行。索引列显示的使用。如果在where条件后出现了between、<、>、in等关键字的查询,就会出现该种类型。这种范围的索引扫描要比全表扫描好,因为它只需要开始于索引的某一个点,而结束于另一个点,不需要全表扫描。
  4. REF:非唯一性索引扫描,返回匹配某个单独值的所有行。其本质上也是一种索引访问,但是能与该索引字段匹配的数据,不止一行。
  5. EQ_REF:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。读取本表中和关联表表中的每行组合成的一行,当连接使用索引的所有部分时, 索引是主键或唯一非 NULL 索引时, 将使用该值。即这种类型常出现在join查询中
  6. CONST:表示通过一次索引就可以找到,const常用于比较primary key或者unique索引,因为它们只需要匹配一行数据,所以查询的速度很快。如将主键字段作为查询条件,MySQL就能够将此次的查询转换为一个常量。
  7. SYSTEM:表只有一行记录(等于系统表),这是const类型的一个特例,平时很少出现,可以忽略不计。

查询效率由高到低分别是:

完整版:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > uniqe_subquery > index_subquery > range > index > all

精简版:system > const > eq_ref > ref > range > index > all

一般SQL被优化到range级别即可,最好能到达ref。切记,不要为了优化而优化


举例说明

该字段的含义比较简单,即代表在此次查询中,使用了什么类型。属于如果是最简单的select * from table 那就是一个全表扫描,其对应的类型就是all。同理,只要满足range属性出现的条件,该属性值就会是range,如下:

Explain执行计划详解_MySQL_10

注意,id字段是主键,所以就自带了唯一索引。type的很多属性值的前提条件,都是针对索引列才有效的。


3.6、possible_keys

显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被实际使用。

例如,我给test表新建了一个唯一索引和普通索引,加上test表的id字段是主键,那么它还会有一个主键索引。这样就是三个索引,即我们的possible_keys就会有三个值

Explain执行计划详解_MySQL_11

Explain执行计划详解_MySQL_12


3.7、key

在上面possible_key的基础上,key表示真实用到的索引

在possible_key的举例中,我们发现key的属性值为primary,即表示我们此次的查询中,真正使用到的索引类型是主键索引。

如果查询中出现了覆盖索引,则索引列仅出现在key列表中。如:

Explain执行计划详解_MySQL_13

我们的id列是索引列,由于查询的字段仅包含索引列,所以满足我们查询中出现了覆盖索引。以至于我们的possible_keys列中没有值,表示此次查询可使用的索引为0,但是真实在查询时却使用到了唯一索引。(如果我们这里没有新建索引,那么这个字段的属性就会是primary)

该属性值可以用来帮我们分析一下查询中的一些特殊情况,比如索引失效。


3.8、key_len

该列主要表示索引的字节的长度。在不损失精度的情况下,数字越小越好。其显示的值为索引字段的最大可能长度,而非实际使用的长度,即key_len是根据表定义计算得到的,而不是通过表内的检索得出的。

计算该长度相关注意事项:

  • int类型占4个字节
  • 在UTF8的字符集中,一个字符占用3个字节。char为3n,varchar为3n+2
  • datetime类型占用3个字节
  • 如果字段可以为null,会比字段不能为null多一个。会多出一个字节用来维护数据可以为null


3.9、ref

表示上述表的连接匹配条件,哪些列或常量被用于查找索引列上的值。显示索引的哪一列被使用了,如果可能的话是一个常数。

在使用索引的时候,会用哪几个值去索引中找对应的数据,这里的哪几个值,指的就是被索引引用到的值。

显示了在key列记录的索引中查找值所用的列或常量,值为null时仅表示啥都没使用。

示例:

Explain执行计划详解_字段_14


3.10、rows

表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数

参考ref中的例子。我们在对e表进行查询时,由于使用到了主键索引,即数据唯一,所以我们最终所需要的行也就是一行。

3.11、filtered

MySQL5.7之后的版本,默认就有这个字段。这个字段表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的百分比。


3.12、Extra

包含不合适在其他列中展示,但是十分重要的额外信息

属性值及其含义

  • Using filesort:MySQL会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行读取。MySQL中无法利用索引完成的排序操作,称为”文件排序“(索引本身有序,排序时如果没有使用到它,就会产生。常见于排序order by 和分组查询group by语句中)
  • Using temporary:使用了临时表保存中间结果,MySQL在对查询结果排序时使用到了临时表。
  • Using index:表示响应的查询操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率很高。如果同时出现了Using where,表明索引被用来执行索引键值的查找;如果没有同时出现Using where,表明索引用来读取数据而非执行查找动作。
  • Using where:使用了where条件进行过滤
  • Using join buffer:使用了连接缓存
  • Impossible where:where子句的值总是false,无法获取到任何元素(where id= 1 and id = 2)
  • Select tables optimized away:在没有group by子句的情况下,基于索引优化的min/max操作或者对于MyISAM存储引擎优化count(*) 操作,不必等到执行阶段在进行计算,查询执行计划生成阶段即完成优化
  • Distinct:优化distinct操作,在找到第一个匹配的元组后即停止找同样值得动作


举报

相关推荐

0 条评论