Explain
MySQL 的 EXPLAIN 是一个用于分析 SQL 查询执行计划的工具,它能帮助开发者理解查询的执行方式、索引使用情况、表之间的关联顺序等,从而优化查询性能。以下是对 EXPLAIN 的详细介绍:
1. 基本用法
在 SQL 语句前添加 EXPLAIN 或 EXPLAIN FORMAT=JSON 即可查看执行计划:
EXPLAIN SELECT * FROM users WHERE id = 1;或者(输出更详细的 JSON 格式):
EXPLAIN FORMAT=JSON SELECT * FROM users WHERE id = 1;2. 输出字段解释
EXPLAIN 的结果包含以下关键字段:
| 字段名 | 说明 |
|---|---|
| id | 查询的标识符(同一查询的多个子查询可能共享相同 id)。 |
| select_type | 查询类型(如 SIMPLE, PRIMARY, SUBQUERY, DERIVED, UNION 等)。 |
| table | 当前操作涉及的表名。 |
| partitions | 匹配的分区(如果表已分区)。 |
| type | 访问类型(关键指标),性能从优到劣排序: system > const > eq_ref > ref > range > index > ALL。 |
| possible_keys | 可能使用的索引。 |
| key | 实际使用的索引。 |
| key_len | 使用的索引长度(字节)。 |
| ref | 索引与哪些列或常量比较。 |
| rows | 预估需要扫描的行数(越小越好)。 |
| filtered | 过滤后剩余行数的百分比。 |
| Extra | 额外信息(如 Using where, Using index, Using temporary, Using filesort 等)。 |
3. 关键字段详解
(1) type
- const:通过主键或唯一索引直接找到一行(最优)。
- eq_ref:联表查询时,主键或唯一索引匹配(如
JOIN ... ON a.id = b.id)。 - ref:非唯一索引查找。
- range:索引范围扫描(如
BETWEEN,IN,>)。 - index:全索引扫描(比全表扫描稍快)。
- ALL:全表扫描(需优化)。
(2) Extra
- Using index:覆盖索引(无需回表)。
- Using where:需在存储引擎返回后进一步过滤。
- Using temporary:使用临时表(常见于
GROUP BY或ORDER BY未用索引)。 - Using filesort:需额外排序(可尝试用索引优化排序)。
- Using index condition:索引下推
4. 优化示例
假设有一个查询:
EXPLAIN SELECT * FROM orders WHERE user_id = 100 ORDER BY order_date;输出分析:
- 如果
type是ALL,且key为空,说明未使用索引,全表扫描。 优化方法:为
user_id和order_date添加联合索引:ALTER TABLE orders ADD INDEX idx_user_order (user_id, order_date);优化后,
type应为ref,Extra显示Using index。
5. 注意事项
- 估算值:
rows是统计信息估算的值,可能与实际有偏差。 - 不执行查询:
EXPLAIN仅生成执行计划,不实际执行 SQL。 索引失效场景:
- 对索引列使用函数或运算(如
WHERE YEAR(date) = 2023)。 - 数据类型不匹配(如字符串列用数字查询)。
- 使用
OR或LIKE '%前缀%'。
- 对索引列使用函数或运算(如
- JSON 格式:
EXPLAIN FORMAT=JSON提供更详细的执行步骤和成本估算。
6. 高级用法
EXPLAIN ANALYZE(MySQL 8.0+):实际执行查询并返回详细执行时间(慎用于生产环境):
EXPLAIN ANALYZE SELECT * FROM users WHERE id = 1;优化器跟踪:查看优化器如何选择执行计划:
SET optimizer_trace = 'enabled=on'; SELECT * FROM users WHERE id = 1; SELECT * FROM information_schema.optimizer_trace;
通过 EXPLAIN 分析执行计划,可以快速定位慢查询的瓶颈,优化索引和 SQL 写法,显著提升数据库性能。