做 MySQL 查询优化遇到明明建了索引查询仍然很慢,看这个 SQL 的执行计划,看它到底有没有用到索引,执行的具体情况。我们可以用 EXPLAIN 命令查看 SQL 的执行计划,SQL 优化的重要性和执行计划密切相关。
EXPLAIN 能够让我们了解到MySQL将如何执行出现在 EXPLAIN 之后的那条 SQL 语句,例如:
EXPLAIN SELECT score.* FROM score INNER JOIN grade_event ON score.event_id = grade.event_id AND grad_event.event_id = 14;
在MySQL 5.6.3之前,该语句必须为SELECT。自MySQL5.6.3起,该语句可以为 SELECT、DELETE、INSERT或UPDATE。
在 EXPLAIN 关键字之后,可以指定一个可选的指示器,指明要产生的输出类型:
例如:
会输出如图内容,这些字段的意思都是啥,是今天这篇文章的重点。
EXTENDED
选项将使 EXPLAIN 语句生成更多的执行计划信息。在 EXPLAIN 语句执行完毕之后立刻执行 SHOW WARNINGS 语句可以查看这些信息。
FORMAT
表明的是用“传统”格式(默认)产生输出,还是用JSON格式产生输出。JSON输出包含了扩展的和可用的分区信息。此选项是在MySQL5.6.5里引入的。
id
这个输出行所对应的的 select 语句的ID 编号。如果语句包含子查询,或该语句中使用了 UNION,那么语句汇总可以有多个 select 子句。
select_type
这个输出行所对应的的 select 语句类型如下表所示。
类型 | 含义 |
SIMPLE | 不带UNION或子查询部分的SELECT子句 |
PRIMARY | 最外层或最左侧的SELECT语句 |
UNION | UNION里的第二条或最后的SELECT子句 |
DEPENDENT UNION | 和UNION相似,但需要依赖于某个外层查询 |
UNION RESULT | UNION的结果 |
SUBQUERY | 子查询中的第一个SELECT子句 |
DEPENDENT SUBQUERY | 和SUBQUERY相似,但需要依赖于某个外层查询 |
DERIVED | FROM子句里的子查询 |
UNCASHEABLE SUBQUERY | 无法缓存的子查询结果 |
UNCASHEABLE UNION | 无法缓存的子查询UNION的第二条或随后的SELECT子句 |
table
输出行引用的那个表。
partitions
将要使用的分区。只有出现PARTITIONS选项时才显示这列。对于非分区表,这个值为NULL。
type
MySQL将执行的连续类型。这些类型(从优到劣)包括system const eq_ref ref ref_or_null index_merge unique_subquery index_subquery range index和ALL。排在前面的类型有更强的限制性,这意味着MySQL在检索的过程中检查的行会相对少一些。
possible_keys
MySQL认为在 名称出现在table 列里的那个表里查找行时可能会用到索引。如果这个输出列里是NULL,则表明没有找到索引。
key
MySQL在指定表里查找行时实际用到的索引。(如果MySQL使用了 index_merge 连续类型,这里可能会列出几个键,因为优化器会使用几个索引来处理查询。)如果这个输出里的值时NULL,则表明没有再该表里找到这样的索引。
key_len
实际使用的索引的长度。若MySQL会使用索引的最左前缀,则此数字可能会小于全文索引行的长度。
ref
MySQL 用来与索引值进行比较的值。单次 const 或 ‘???’ 表示的是对常数进行比较,若是某个列的名称,则表示逐个比较列。
rows
MySQL 为完成查询而需要在表里检查的行的估计百分比。这个值输出的值的乘积就是索引表必须检查的行的各种可能的组合的估计值。
filtered
它指的是将于前面的表进行连接的行的估计百分比,若存在 EXTENDED 选项,则会显示此列。
Extra
其他执行计划相关的信息。这个值或者为空白,或者包含一个或多个下面这样的值。
- Using filesort 需要将索引值写到文件中并且排序,以便安排顺序检索相关行。
- Using index MySQL 可以不必检查数据行,只使用索引信息就能检索表信息。
- Using temporary 利用SELECT 语句只能怪 WHERE 子句里 的信息查询行。
此外,还有很多其他的值并未列在这里。与Extra 值有关的更多信息请MySQL-EXPLAIN执行计划Extra解释。