EXPLAIN是优化SQL查询不可或缺的工具。掌握其输出结果中 type和 Extra列的含义,是定位性能问题的关键。通常的优化路径是:避免出现 ALL类型的全表扫描,并通过创建合适的索引来将查询类型提升到 ref或 range,同时留意 Extra列中是否有 Using temporary或 Using filesort等需要优化的提示。
下面这个表格汇总了使用 EXPLAIN时返回结果中各字段的核心含义。
| 字段 | 含义与解读要点 |
|---|---|
**id** |
SELECT 查询的序列号。id值越大,执行优先级越高;id相同,则从上往下执行。 |
**select_type** |
查询的类型,例如简单查询(SIMPLE)、主查询(PRIMARY)、子查询(SUBQUERY)、派生表查询(DERIVED)等。 |
**type** |
访问类型 ,即MySQL决定如何查找表中的行。这是判断查询效率的关键指标,从优到劣常见的有:const/eq_ref> ref> range> index> ALL(全表扫描,需要优化)。 |
**possible_keys** |
查询可能使用到的索引。 |
**key** |
查询实际使用 到的索引。如果为 NULL,则表示未使用索引。 |
**key_len** |
使用的索引字节数。可用于判断索引是否被完全利用。 |
**rows** |
MySQL 估算需要扫描的行数。通常数值越小越好。 |
**Extra** |
包含查询执行的附加信息 。非常重要,常出现如 Using filesort(需要额外排序)、Using temporary(使用了临时表)等,都是需要关注的优化点。 |
如何使用 EXPLAIN
使用 EXPLAIN非常简单,只需在需要分析的 SQL 语句前加上 EXPLAIN关键字即可。从 MySQL 5.6.3 开始,它不仅可以分析 SELECT语句,还可以分析 DELETE、INSERT、REPLACE和 UPDATE语句。
-- 基本用法
EXPLAIN SELECT * FROM your_table WHERE column_name = 'value';
-- 也可以使用 DESCRIBE 或 DESC,它们是 EXPLAIN 的同义词
DESCRIBE SELECT * FROM your_table;
DESC SELECT * FROM your_table;
在 MySQL 8.0 及更高版本中,还可以指定输出格式以获得更详尽或更直观的信息:
-
FORMAT=TRADITIONAL:默认格式,以表格形式展示。 -
FORMAT=JSON:提供非常详细的 JSON 格式信息,包含成本估算等更多数据。 -
FORMAT=TREE:MySQL 8.0.16 及以上版本可用,以树形结构展示执行过程,能清晰显示哈希连接等高级特性。-- 指定输出格式
EXPLAIN FORMAT=JSON SELECT * FROM your_table;
此外,MySQL 8.0.18 引入了 EXPLAIN ANALYZE ,这是一个非常强大的功能。它不仅显示执行计划,还会实际执行该语句,并返回详细的执行时间、返回行数等实际运行数据,能更准确地评估性能。
-- 使用 EXPLAIN ANALYZE 获取实际执行数据(MySQL 8.0.18+)
EXPLAIN ANALYZE SELECT * FROM your_table WHERE column_name = 'value';
重点字段详解与优化提示
-
type 字段(核心性能指标)
这是评估查询效率最重要的字段。应该致力于让查询的
type至少达到range级别,最好能达到ref。-
system/const:性能最佳。通常通过主键(PRIMARY KEY)或唯一索引(UNIQUE INDEX)进行等值查询时出现,表示只返回一行数据。 -
eq_ref:常见于多表关联查询,使用主键或唯一索引作为关联条件,对于前一张表的每一行,当前表只有一条记录与之匹配。 -
ref:使用普通索引进行查询,可能会返回多条匹配的记录。这是非常常见的、高效的索引使用方式。 -
range:使用了索引进行范围扫描(如BETWEEN、IN、>、<等)。 -
index:全索引扫描。虽然比全表扫描(ALL)好,因为它只遍历索引树,但如果索引很大,速度也可能较慢。 -
ALL:全表扫描 。这意味着MySQL需要读取整个表来找到匹配的行。在数据量大的情况下,这是必须优化的信号。通常的解决方案是为查询条件创建合适的索引。
-
-
Extra 字段(重要优化线索)
这个字段提供了大量关于MySQL如何解析查询的额外信息。以下是一些需要特别注意的值:
-
Using index:覆盖索引。表示查询的列都包含在索引中,无需回表读取数据行,性能非常好。 -
Using where:表示服务器在存储引擎检索行后进行了进一步的过滤。 -
Using temporary:表示MySQL为了执行查询创建了临时表 。这通常发生在排序(ORDER BY)和分组(GROUP BY)操作中,如果可能,应考虑通过索引来优化。 -
Using filesort:表示MySQL无法利用索引进行排序,需要额外的排序操作 。如果可能,应尝试为ORDER BY子句创建合适的索引。
-
使用技巧与局限性
-
结合
SHOW WARNINGS:在执行EXPLAIN后,立即运行SHOW WARNINGS;,可以查看优化器优化后的SQL语句,有时能提供更多线索。 -
注意估算值 :
EXPLAIN(不包括ANALYZE)输出的rows等字段是基于统计信息的估算值,并非精确值。 -
局限性 :
EXPLAIN不会考虑查询缓存的影响,也不能显示触发器、存储过程对查询的影响,并且它只解释查询过程,不执行查询(EXPLAIN ANALYZE除外)。