顾名思义, Extra 列是用来说明一些额外信息的,包含不适合在其他列中显示但十分重要的额外信息。 我们可以通过这些额外信息来 更准确的理解MySQL到底将如何执行给定的查询语句。MySQL提供的额外信息 有好几十个,我们就不一个一个介绍了,所以我们只挑选比较重要的额外信息介绍给大家。
当查询语句没有 FROM 子句时将会提示该额外信息,比如:
当查询语句的 WHERE 子句永远为 FALSE 时将会提示该额外信息
EXPLAIN SELECT * FROM s1 WHERE 1 != 1;
当我们使用全表扫描来执行对某个表的查询,并且该语句的WHEE子句中有针对该表的搜索条件时,在`Extra列中会提示上述额外信息。比如下边这个查询:
EXPLAIN SELECT * FROM s1 WHERE common_field = 'a';
当使用索引访问米执行对某个表的查询,并且该语句的where子句中有除了该索引包含的列之外的其他搜索条件时,在Extra列中也会提示上述额外信息。
EXPLAIN SELECT * FROM s1 WHERE key1 = 'a' AND common_field = 'a';
虽然使用了key1索引,但是还是用了commmon_field作为搜索条件。
当查询列表处有 MIN 或者 MAX 聚合函数,但是并没有符合WHERE 子句中的搜索条件的记录时。
EXPLAIN SELECT MIN(key1) FROM s1 WHERE key1 = 'abcdefg';
当我们的查询列表以及搜索条件中只包含属于某个索引的列,也就是在可以使用覆盖索引的情况 下,在 Extra 列将会提示该额外信息。比方说下边这个查询中只需要用到 idx_key1 而不需要回表操作:
EXPLAIN SELECT key1 FROM s1 WHERE key1 = 'a';
有些搜索条件中虽然出现了索引列,但却不能使用到索引,比如下边这个查询:
explain SELECT * FROM s1 WHERE key1 > 'z' AND key1 LIKE '%a';
在连接查询执行过程中,当被驱动表不能有效的利用索引加快访问速度,MySQL一般会为其分配一块名叫 join buffer 的内存块来加快查询速度,也就是我们所讲的基于块的嵌套循环算法。
EXPLAIN SELECT * FROM s1 INNER JOIN s2 ON s1.common_field = s2.common_field;
当我们使用左(外)连接,如果where子句中包含要求被驱动表的某个列等于NULL值的搜索条件,而且那个列又是不允许存储NULL值的,那么在该表的执行计划的Extra列就会提示Not exists
额外信息
EXPLAIN SELECT * FROM s1 LEFT JOIN s2 ON s1.key1 = s2.key1 WHERE s2.id IS NULL;
如果执行计划的 Extra 列出现了 Using intersect(...) 提示,说明准备使用 并的方式执行查询,括号中Intersect 索引合 ... 表示需要进行索引合并的索引名称;
如果出现 Using union(...) 提示,说明准备使用 Union 索引合并的方式执行查询。
如果出现 Using sort_union(...) 提示,说明准备使用 Sort-Union 索引合并的方式执行查询。
当我们的 LIMIT 子句的参数为0时,表示压根儿不打算从表中读取任何记录,将会提示该额外信息
EXPLAIN SELECT * FROM s1 LIMIT 0;
文件排序:
很多情况下排序操作无法使用到索引,只能在内存中(记录较少的时候)或者磁盘中(记录较多的时候)进行排序,MySQL把这种在内存中或者磁盘上进行排序的方式统称为文件排序。
#索引列排序
EXPLAIN SELECT * FROM s1 ORDER BY key1 LIMIT 10;
#普通列排序
EXPLAIN SELECT * FROM s1 ORDER BY common_field LIMIT 10;
在许多查询的执行过程中,MySQL可能会借助临时表来完成一些功能,比如去重、排序之类的,比如我们
在执行许多包含DISTINCT'、
GROUP BY、
UNION`等子句的查询过程中,如果不能有效利用索引来完成
查询,MySQL很有可能寻求通过建立内部的临时表来执行查询。如果查询中使用到了内部的临时表,在执行
计划的Extra
列将会显示`Using temporary'提示
EXPLAIN SELECT DISTINCT common_field FROM s1;
同样,分组也需要使用临时表
EXPLAIN SELECT common_field,COUNT(*) AS amount FROM s1 GROUP BY common_field;
但是注意,如果是索引列,则不需要临时表
EXPLAIN SELECT key1,COUNT(*) AS amount FROM s1 GROUP BY key1;
执行计划中出现Using temporary
并不是一个好的效率,因为建立与维护临时表要付出很大成本的,所以
我们~最好能使用索引来替代掉使用临时表。比如扫描指定的索引idx key1即可。
● EXPLAIN不考虑各种Cache
● EXPLAIN不能显示MySQL在执行查询时所作的优化工作
● EXPLAIN不会告诉你关于触发器、存储过程的信息或用户自定义函数对查询的影响情况
● 部分统计信息是估算的,并非精确值
—— 评论区 ——