MySQL EXPLAIN 使用指南
概述
EXPLAIN 语句用于分析 SQL 查询的执行计划,帮助开发者理解 MySQL 如何执行查询并进行性能优化。
来源: https://dev.mysql.com/doc/refman/8.0/en/explain.html
基本语法
TRADITIONAL 格式(默认)
sql
EXPLAIN SELECT Name FROM country WHERE Code LIKE 'A%';TREE 格式
sql
EXPLAIN FORMAT=TREE SELECT Name FROM country WHERE Code LIKE 'A%';JSON 格式(最详细)
sql
EXPLAIN FORMAT=JSON SELECT Name FROM country WHERE Code LIKE 'A%';EXPLAIN 输出列详解
| 列名 | 说明 |
|---|---|
| id | 查询的序号,表示执行顺序 |
| select_type | 查询类型(SIMPLE、PRIMARY、SUBQUERY 等) |
| table | 表名 |
| partitions | 使用的分区 |
| type | 连接类型/访问类型 |
| possible_keys | 可能使用的索引 |
| key | 实际使用的索引 |
| key_len | 使用的索引长度(字节) |
| ref | 与索引比较的列或常量 |
| rows | 估计需要检查的行数 |
| filtered | 行过滤百分比 |
| Extra | 额外信息 |
来源: https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
连接类型(按性能从优到劣排序)
| 类型 | 说明 | 性能 |
|---|---|---|
| system | 表只有一行记录(const 的特例) | ⭐⭐⭐⭐⭐ |
| const | 最多匹配一行,通常为主键或 UNIQUE 索引查询 | ⭐⭐⭐⭐⭐ |
| eq_ref | 每个组合读取一行,使用 PRIMARY KEY 或 UNIQUE NOT NULL 索引 | ⭐⭐⭐⭐ |
| ref | 非唯一索引查询,可能返回多行 | ⭐⭐⭐ |
| range | 索引范围扫描 | ⭐⭐⭐ |
| index | 全索引扫描 | ⭐⭐ |
| ALL | 全表扫描(最差) | ⭐ |
来源: https://dev.mysql.com/doc/refman/8.0/en/explain-output.html来源: https://dev.mysql.com/doc/refman/8.0/en/dynindex-jointype.html
Const 示例
sql
SELECT * FROM _tbl_name_ WHERE _primary_key_=1;
SELECT * FROM _tbl_name_
WHERE _primary_key_part1_=1 AND _primary_key_part2_=2;Eq_ref 示例
sql
SELECT * FROM _ref_table_,_other_table_
WHERE _ref_table_._key_column_=_other_table_._column_;Extra 列常见值
| 值 | 说明 |
|---|---|
| Using index | 覆盖索引,无需回表查询 |
| Using where | 使用了 WHERE 条件过滤 |
| Using where with pushed condition | 条件推送优化 |
| Using temporary | 使用了临时表(需优化) |
| Using filesort | 使用了文件排序(需优化) |
| Backward index scan | 反向索引扫描 |
来源: https://dev.mysql.com/doc/refman/8.0/en/engine-condition-pushdown-optimization.html来源: https://dev.mysql.com/doc/refman/8.0/en/descending-indexes.html
实例解析
示例 1:范围查询
sql
EXPLAIN SELECT a, b FROM t1 WHERE a < 2\G输出:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: range
possible_keys: a
key: a
key_len: 5
ref: NULL
rows: 2
Extra: Using where with pushed condition来源: https://dev.mysql.com/doc/refman/8.0/en/engine-condition-pushdown-optimization.html
示例 2:ORDER BY 使用索引
sql
EXPLAIN SELECT * FROM t1 ORDER BY a ASC\G输出:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
partitions: NULL
type: index
possible_keys: NULL
key: a_desc_b_asc
key_len: 10
rows: 1
filtered: 100.00
Extra: Backward index scan; Using index来源: https://dev.mysql.com/doc/refman/8.0/en/descending-indexes.html
示例 3:复合索引查询
sql
EXPLAIN SELECT COUNT(*) FROM t1 WHERE i1 = 3 AND d = '2000-01-01'\G输出:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t1
type: ref
possible_keys: PRIMARY,k_d
key: k_d
key_len: 8
ref: const,const
rows: 1
Extra: Using index来源: https://dev.mysql.com/doc/refman/8.0/en/index-extensions.html
最佳实践
- 避免
type=ALL:全表扫描通常是性能瓶颈 - 关注
rows列:与EXPLAIN ANALYZE的实际结果对比 - 优化
Extra列:尽量避免Using temporary和Using filesort - 使用合适的索引:确保
key列显示预期的索引
来源: https://dev.mysql.com/doc/refman/8.0/en/explain-output.html
文档生成时间:2026-05-19数据来源:MySQL 8.0 Reference Manual
