MySQL之explain执行计划

535 阅读5分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

MySQL中提供explain关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何执行SQL语句的,进而可以分析SQL语句的性能瓶颈,为优化我们的SQL语句提供帮助.MySQL5.6之前,只支持select,MySQL5.6之后,explain支持对select、update、delete语句进行分析。

image.png

各字段的含义

id

SQL查询的序列号,可以分析出SQL语句中操作表的顺序

  • 如果id相同,则执行顺序为从上到下

image.png

如以上执行结果:SQL语句操作表的顺序为:先操作表e,再操作ps、j、d、 n表

  • 如果是子查询,id序号会递增,则id越大,其越先被执行

image.png

如以上执行结果(SUBQUERY表示子查询):SQL语句操作表的顺序为:先操作表t3,再操作t2,,最后操作表t1(id越大,优先级越高,越先被执行)

  • id不同,且存在重复的id,则id越大的越先被执行,相同id序号的则执行顺序为从上到下。

select_type

表示SQL的查询类型

  • SIMPLE:简单的select查询,不包含子查询或者UNION
  • PRIMARY:查询中若包含任何复杂的子部分,则最外层查询被标记为PARIMARY类型
  • SUBQUERY:在select或where中包含子查询
  • DERIVED:在from列表中包含的子查询会被标记为DERIVED(衍生的)MySQL会递归执行这些子查询,把结果放在临时表中。
  • UNION:若第二个select出现在union之后,则被标记为UNION;若union包含在from子句的子查询中,则外层select会被标记为DERIVED
  • UNION RESULT:从union表获取结果的select(即union合并两个表后的结果)会被标记为UNION RESULT 如EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2 的执行结果如下:

image.png

table

查询的表名,不一定是实际存在的表名。

  • <unionM,N>: 引用id为M和N UNION后的结果。

  • < derivedN>: 引用id为N的结果派生出的表。派生表可以是一个结果集,例如派生自FROM中子查询的结果。

  • < subqueryN>: 引用id为N的子查询结果物化得到的表。即生成一个临时表保存子查询的结果。

type

表示查询使用的类型(12种) 其查询效率从左到下=右递减

  • system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > range > index > ALL

以下列举几个常见的:

  • system:表中只有一行数据或者是空表,如果是Innodb引擎表,type列在这个情况通常都是all或者index。

  • const:表示通过索引一次就查找到,因为只匹配一行,所以能够很快就查询出来,如将主键=某个值放在where的后面,MySQL就会将该查询转换为一个常量。 如:EXPLAIN SELECT * FROM t1 WHERE t1.id=1

image.png

  • eq_ref:唯一索引扫描,对于每个索引键,表中只有一条记录与之匹配,如主键索引或唯一索引。
  • ref:非唯一索引扫描,返回匹配某个单独值的所有行
  • range:范围扫描,值检索给定范围的记录,使用一个索引来选择符合的记录。如在where语句中使用了between、<、>、in等的查询。 如EXPLAIN SELECT * FROM t1 WHERE id>2 (id为主键索引,如果不是索引,会造成全表扫描)
  • index:扫描所有索引,index与ALL的区别为index类型只遍历索引树,虽然说ALL和index都是读全表,但是index是从索引中读的,而ALL是从磁盘中读的,所以index通常比index快。
  • ALL:全表扫描已找到匹配的记录。

possible_keys

显示SQL查询可能使用到的索引的名称

key

显示SQL查询真正使用到的索引的名称

key_len

表示SQL查询用到的索引长度(字节数)

  • key_len表示的值为索引字段的最大可能长度,并非实际使用长度,key_len是通过表字段的定义得到的,而不是通过表内检索出来的。

ref

显示索引的哪一列被使用了

  • 如果是使用常数等值查询,则为const,如EXPLAIN SELECT * FROM t1 WHERE id=2。也可以是表示哪些列被用来查找在索引列上的值,如EXPLAIN SELECT * FROM USER WHERE uname IN (SELECT uname FROM USER WHERE uid>3 ),以下执行结果ref字段中的demo.user.uname就表示uname字段的列被用于查找索引列上的值。

image.png

rows

估算的需要扫描的行数

  • rows可以根据表的统计信息以及索引选用情况,估算出找到目标记录所需要扫描的的行数。

filtered

查询命中率

  • 表示存储引擎返回的数据在server层过滤后,剩下多少满足查询的记录数量的比例。

extra

表示在其他列中显示但十分重要的额外信息

  • Using filesort:表示 MySQL 需额外的排序操作, 不能通过索引顺序达到排序效果。MySQL中无法利用索引完成的排序操作被称为文件排序。如EXPLAIN SELECT * FROM t1 ORDER BY age(age字段上没有建立索引)

image.png

  • Using temporary:使用了临时表保存中间结果,MySQL在对查询结果进行排序时会使用临时表。

  • Using index:覆盖索引扫描(覆盖索引是指SQL所要查询的字段都包含在当前索引的字段中),表示查询在索引树中就可查找到所需数据, 不用扫描表数据文件(无需回表,所查询的字段都在当前索引的叶子结点上),效率较高。如select id from t1(id为主键索引)

  • Using join buffer:使用了连接缓存

  • impossible where:where子句的值总是false,不能用来获取任何元组。

  • select tables optimized away:在没有Group by子句的情况下,基于索引优化MIN/MAX操作。如EXPLAIN SELECT MAX(id) FROM t1(id为主键索引)

  • distinct:优化distinct操作,在找到第一个匹配的记录后就停止查找相等值的动作。

🏁以上就是对explain的详细解释,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞吧😻😍 默认标题_动态分割线_2021-07-15-0.gif