摘要
Mysql Version:5.7.36
# 一:前言
EXPLAIN——分析sql语句执行效率是否高效,有没有使用到索引之类的;主要就是看懂它的结果,然后判断sql需要优化。
Mysql 5.6 之前的版本只能对 select 语句进行 explain,之后的版本可以对其他命令。
# 三:结果列
列名 | 说明 |
---|---|
id | 执行编号,表示sql语句中select的执行顺序,有几个select就有几个id,按照select出现的顺序呈现结果 |
select_type | 显示本行是简单或复杂select。如果查询有任何复杂的子查询,则最外层标记为PRIMARY(DERIVED、UNION、UNION RESUlT) |
table | explain 访问的表是哪一个 |
type | 表关联类型或访问类型,重要的一列,是判断查询是否高效的一句:也就是Mysql决定如何查找表中的行就看这个列 |
possible_keys | 揭示哪一些索引可能有利于高效的查找 |
key | 显示Mysql采用哪个索引来查找 |
key_len | 显示Mysql在索引里使用的字节数 |
ref | 显示了之前的表在key列记录的索引中查找值所用的列或常量 |
rows | 为了找到所需的行而需要读取的行数,估算值,不精确。通过把所有rows列值相乘,可粗略估算整个查询会检查的行数 |
Extra | 额外信息,如using index、filesort等 |
# 3.1 id 列
有几种情况:
- id 相同,执行顺序由上而下
- id 不同,序号会递增。值越大优先级越高,就越先执行
# 3.2 select_type
加粗的都是常见的:
simple:简单查询。查询不包含子查询和 union,比如上面简介中演示的语句
primary:跟上面相反,如果查询包含子查询和 union,就会被标记为 primary
subquery:见名知义,包含在 select 中的子查询(不在 from 子句中)
derived:在 from 子句中子查询,MySQL 会将结果存放在一个临时表中,也称为派生表(derived 的英文含义)
union:表示此查询是 UNION 中的第二个或随后的查询
union result:从 union 临时表检索结果的 select
dependent union:此查询是 UNION 中的第二个或随后的查询,其次取决于外面的查询
uncacheable union:此查询是 UNION 中的第二个或随后的查询,同时意味着 select 中的某些特性阻止结果被缓存于一个 Item_cache 中
dependent subquery:子查询中的 第一个 select,同时取决于外面的查询
uncacheable subquery:子查询中的 第一个 select,同时意味着 select 中的某些特性阻止结果被缓存于一个 Item_cache 中
# 3.3 table
当 from 子句中有子查询时,table 列是 <derivenN> 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询
当有 union 时,UNION RESULT 的 table 列的值为 <union1,2>,1 和 2 表示参与 union 的 select 行 id
# 3.4 type
结果有很多,性能从最优到最差为:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
常见的几个:
ALL:全表扫描,性能极差。敲黑板哈,这种类型是不应该出现的,一定还可以加索引优化。
index:全索引扫描,跟 ALL 差不多,不同的是 index 是扫描整棵索引树,比 ALL 要快些。
range:范围扫描,通常出现在
in (), between ,> ,<, >=
等操作中。使用一个索引来检索给定范围的行。ref:索引查找,不使用唯一索引,使用普通索引或者唯一性索引的部分前缀,索引要和某个值相比较,可能会找到多个符合条件的行。
eq_ref:最多只返回一条符合条件的记录。在使用唯一性索引或主键查找时会出现该值,非常高效。
const、system:该表至多有一个匹配行,在查询开始时读取,或者该表是系统表,只有一行匹配。其中 const 用于在和 primary key 或 unique 索引中有固定值比较的情形。
null:在执行阶段用不着再访问表或索引。
# 3.5 possible_keys
表示 MySQL 执行查询可能会使用那些索引来查找,如果为 null,可考虑在该列加个索引。
# 3.6 key
表示 MySQL 执行查询实际使用那些索引来查找,如果为 null,则证明没有使用索引。如果想强制使用或者忽略索引可以在查询语句加 force index(想要强制使用的索引名)或者 ignore index(想要忽略的索引名)
如果 possible_keys 有列,而 key 显示 null 的情况,可能是因为表数据不多,加索引作用也不大
# 3.7 key_len
在索引里使用的字节数,当 key 列的值为 NULL 时,则该列也是 NULL
索引的最大长度是 768 字节,字符串过长时,MySQL 会将前半部分提出来做索引,这点大家需要注意。(不过一般也不会在这么长的字段上建索引)
# 3.8 ref
那些字段或者常量被用来和 key 列记录的索引配合查找值,常见的有:const(常量),func,NULL,字段名(例:film.id)
# 3.9 rows
mysql 估计要读取并检测的行数,注意这个不是结果集里的行数。(只是个预测的数量)
# 3.10 Extra
额外信息,也非常重要
Using index:使用覆盖索引,表示查询索引就可查到所需数据,不用回表,说明性能不错。
Using where:在存储引擎检索行后再进行过滤,就是先读取整行数据,再按 where 条件进行取舍。
Using temporary:mysql 需要创建一张临时表来处理查询,一般是因为查询语句中有排序、分组、和多表 join 的情况,一般是要进行优化的。
Using filesort:对结果使用一个外部索引排序,而不是按索引次序从表里读取行,一般有出现该值,都建议优化去掉,因为这样的查询 CPU 资源消耗大。
https://segmentfault.com/a/1190000023565685 https://segmentfault.com/a/1190000008131735 https://learnku.com/articles/38719 https://blog.csdn.net/u014745069/article/details/104173763 https://www.itmuch.com/mysql/explain/ https://www.jianshu.com/p/ea3fc71fdc45 https://xlk3099.github.io/post/understand_explain_in_mysql/ https://www.cnblogs.com/xuanzhi201111/p/4175635.html