MySQL 的 执行计划(Execution Plan) 是优化器根据 SQL 语句生成的查询执行路径的详细说明。通过分析执行计划,可以了解 MySQL 如何处理 SQL 查询(如索引使用情况、表连接顺序等),进而优化查询性能。
1. 获取执行计划
使用 EXPLAIN
或 EXPLAIN FORMAT=JSON
命令:
explain select * from students where id=2
EXPLAIN FORMAT=JSON select * from students where id=2
2. 执行计划输出列解析
EXPLAIN
输出的关键列及其含义:
列名 | 说明 |
---|---|
id | 查询的序列号(层级),相同 id 表示同一层级,值越大优先级越高(子查询等)。 |
select_type | 查询类型,如 SIMPLE (简单查询)、PRIMARY (外层查询)、SUBQUERY 等。 |
table | 当前操作的表名或别名。 |
partitions | 匹配的分区(若表有分区)。 |
type | 访问类型(性能关键指标),常见值:ALL 、index 、range 、ref 、eq_ref 、const 。 |
possible_keys | 可能使用的索引。 |
key | 实际使用的索引。 |
key_len | 使用的索引长度(字节数)。 |
ref | 与索引比较的列或常量(如 const 或 other_table.column )。 |
rows | 预估扫描的行数(越小越好)。 |
filtered | 查询条件过滤后剩余行的百分比(与 rows 结合使用)。 |
Extra | 额外信息(如 Using where 、Using temporary 、Using filesort 等)。 |
3. 关键指标详解
type(访问类型)
按性能从优到劣排序:
-
const
:通过主键或唯一索引直接找到一行(最优)。 -
eq_ref
:联表查询时,使用主键或唯一索引匹配(如JOIN ... ON a.id = b.id
)。 -
ref
:使用非唯一索引查找。 -
range
:索引范围扫描(如BETWEEN
、IN
、>
等)。 -
index
:全索引扫描(遍历索引树)。 -
ALL
:全表扫描(性能最差,需优化)。
Extra(额外信息)
-
Using where
:WHERE 条件过滤。 -
Using index
:覆盖索引(无需回表)。 -
Using temporary
:使用临时表(常见于GROUP BY
、ORDER BY
)。 -
Using filesort
:文件排序(需优化索引或查询)。 -
Using join buffer
:使用连接缓存(联表查询较大时)。
4. 常见性能问题
-
全表扫描(
type=ALL
):未命中索引,需检查 WHERE 条件或添加索引。 -
未使用索引(
key=NULL
):可能索引不匹配或统计信息过时。 -
Using filesort
/Using temporary
:排序或分组未利用索引,需优化 SQL 或索引。 -
rows
值过大:预估扫描行数多,可能导致慢查询。
5. 优化建议
索引优化
-
为 WHERE、JOIN、ORDER BY、GROUP BY 涉及的列添加索引。
-
使用覆盖索引(查询列均在索引中)。
-
避免冗余索引,定期分析索引使用情况。
查询优化
-
避免
SELECT *
,仅选择需要的列。 -
减少子查询,改用 JOIN。
-
优化复杂查询,拆分为多个简单步骤。
其他优化
-
调整
JOIN
顺序,让小表驱动大表。 -
更新表的统计信息:
ANALYZE TABLE table_name;
-
调整数据库配置(如
join_buffer_size
、sort_buffer_size
)。
6. 示例分析
where 条件未加索引 b 表全表扫描
添加索引
create index idx_age on employees(age) ;
7. 高级工具
-
EXPLAIN ANALYZE
(MySQL 8.0.18+):实际执行查询并输出详细耗时(需谨慎使用,会真实执行查询)。 -
优化器跟踪(Optimizer Trace):查看优化器的详细决策过程:
SET optimizer_trace = 'enabled=on';
SELECT * FROM ...; -- 执行查询
SELECT * FROM information_schema.optimizer_trace;