MySQL - explain详解

149 阅读4分钟

explain用法

mysql>  explain 你的语句;

explain字段详解

  • id字段
SQL执行序号, 一条语句内有多少次查询就会自增到几(步长:1),值越大执行时优先级越高
  • select_type字段

查询类型

simple:简单查询,执行语句中不包含子查询及union
primary:主查询,执行sql语句中包含子查询或union
subquery: 子查询,包含在主查询中的子查询
derived:from子句中的子查询,执行时mysql会将结果存储在一个临时表中,当前连接所有语句执行完成后会自动销毁
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个,其他的知道就好。SQL语句尽可能简单,非必须不要使用子查询

  • table字段

当前分析行命中的数据表名称

from 子句中有子查询时,table 列是 < derivenN > 格式,表示当前查询依赖 id=N 的查询,于是先执行 id=N 的查询
当有 union 时,UNION RESULTtable 列的值为 < union1,2 >12 表示参与 unionselect 行 id
  • type字段

SQL访问类型

all:全表扫描,当索引因为某种原因失效或语句中没有where条件时就会触发全表扫描,
index:全索引扫描,不同的是 index 是扫描整棵索引树,比 all 稍微快些。
range:范围查询,当语句中出现inbetween><>=<=等区间操作时会触发
ref:索引查询,使用非唯一索引或者唯一性索引的部分前缀,可能会查询到多个符合条件的数据行
eq_ref:最多只返回一条符合条件的记录。在使用唯一性索引或主键查找时会出现该值,非常高效
const:该表至多有一个匹配行,在查询开始时读取,或者该表是系统表,只有一行匹配
null:在执行阶段用不着再访问表或索引

执行效率从优到差依次为:

system -> const -> eq_ref -> ref -> fulltext -> ref_or_null -> index_merge -> unique_subquery -> index_subquery -> range > index -> all

  • possible_keys字段
SQL执行查询可能会命中哪些来帮助查找,但是也可能会出现possible_keys为null,key确实际使用了索引的情况
  • key字段

SQL执行查询时实际命中了哪些索引

 primary:主键索引

即使创建了索引在查询时也可能会遇到索引未命中或失效的情况,业务场景可能会因为如下原因导致创建的索引失效

1):组合索引不满足最左匹配原则
    [错误示例:]
(2):使用了select *
    [错误示例:select * from table key = xxx]
(3):索引列参与了数学运算
    [错误示例:select * from table where id = 2 - 1]
(4):索引列参使用了内置函数
    [错误示例:select xxx  from table where substr(xxx, 11, 4) = date_format(now(), '%m%d')]
(5):错误的like语句
    [错误示例:select * from table where xxx like '%xxx%']
(6):索引字段传参时错误
    [错误示例:如索引字段类型为varchar,调用时传入了int,反之亦然]
(7):错误的使用or><>=<=
    [错误示例:select xxx from table where id = 1 or xxx = "xxx",示例中如果xxx字段没有添加索引会导致id主键/其他索引失效)
(8):is not nullnot innot exists操作导致索引失效
  • key_len字段

索引使用的字节数

当key值为null时,key_len字段的值也会为null,索引的最大长度是 768 字节,字符串过长时,mysql 会将前半部分提出来做索引,所以不建议将长字段作为索引
  • ref字段
哪些字段或常量参与了和 key 列记录的索引配合查找值,常见的有:const(常量),func,null,字段名
  • rows字段
mysql 估计要读取并检测的行数,但这个并不是结果集里的行数
  • extra字段

额外信息提示列

using index:使用覆盖索引,表示查询索引就可查到所需数据,不用回表,说明性能不错。
using where:在存储引擎检索行后再进行过滤,就是先读取整行数据,再按 where 条件进行取舍。
using temporary:mysql 需要创建一张临时表来处理查询,一般是因为查询语句中有排序、分组、和多表 join 的情况,一般是要进行优化的。
using filesort:对结果使用一个外部索引排序,而不是按索引次序从表里读取行,一般有出现该值,都建议优化去掉,因为这样的查询 CPU 资源消耗大。
  • partitions字段
结果集所在分区,如果数据表未创建分区此字段返回null
  • filtered字段
按表条件过滤的表行的估计百分比。最大值为 100,这意味着没有过滤行。从 100 开始减小的值表示过滤量增加。 rows显示检查的估计行数,rows× filtered显示与下表连接的行数。例如,如果 rows1000 并且 filtered是 50.00 (50%),则要与下表连接的行数是 1000 × 50% = 500