Mysql

关注公众号 jb51net

关闭
首页 > 数据库 > Mysql > MySQL EXPLAIN 字段

MySQL EXPLAIN 字段使用小结

作者:Listen·Rain

EXPLAIN 是 MySQL 提供的查询执行计划分析工具,执行结果包含 12 个核心字段,下面就来详细的介绍一下EXPLAIN 字段使用小结,感兴趣的可以了解一下

EXPLAIN 是 MySQL 提供的查询执行计划分析工具,在 SELECT 语句前加上 EXPLAIN 即可查看优化器如何执行 SQL。执行结果包含 12 个核心字段。

一、执行顺序相关字段

字段含义核心要点
id查询序列号,标识 SELECT 的执行顺序① id 相同 → 从上往下顺序执行
② id 不同 → id 值越大越先执行(子查询 id 递增)
③ id 为 NULL → 最后执行(如 UNION RESULT)
select_type查询类型,区分简单/复杂查询见下方详细分类
table当前访问的表名派生表显示为 <derived N>,UNION 显示为 <union M,N>
partitions匹配的分区仅分区表有效,否则为 NULL

select_type 取值详解

含义示例
SIMPLE简单查询,无子查询/UNIONSELECT * FROM t1 WHERE id=1
PRIMARY最外层查询(含子查询时)包裹子查询的外层 SELECT
SUBQUERYSELECT 或 WHERE 中的子查询SELECT * FROM t1 WHERE id IN (SELECT id FROM t2)
DEPENDENT SUBQUERY依赖外部查询的子查询子查询引用了外层表的列
DERIVEDFROM 子句中的子查询(派生表)SELECT * FROM (SELECT * FROM t1) a
UNIONUNION 中第二个及之后的 SELECTSELECT * FROM t1 UNION SELECT * FROM t2
DEPENDENT UNION依赖外部查询的 UNIONUNION 子查询引用外层表
UNION RESULTUNION 的结果合并id 通常为 NULL
MATERIALIZED物化的子查询(MySQL 8.0+)子查询结果缓存为临时表

📌 优先级排序:SIMPLE > PRIMARY > UNION/SUBQUERY/DERIVED > DEPENDENT SUBQUERY/DEPENDENT UNION

二、索引与访问方式(⭐ 核心重点)

字段含义说明
type访问类型/连接类型⭐ 性能核心指标,从优到差排序见下方
possible_keys可能使用的索引优化器的"备选方案",不一定实际使用
key实际使用的索引为 NULL 表示未使用索引
key_len索引使用的字节数判断联合索引用了几列,计算规则见下方
ref索引与谁比较const(常量)、字段名、func 等
rows预估扫描行数越小越好,基于统计信息的估算值
filtered过滤后剩余比例(%)最终行数 ≈ rows × filtered / 100
Extra额外执行信息⭐ 性能问题的"信号灯",见下方

🔥 type 访问类型(从最优到最差)

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge >
unique_subquery > index_subquery > range > index > ALL
类型含义场景性能
system表只有一行记录(const 特例)系统表、LIMIT 1 且只有一行⭐⭐⭐⭐⭐
const主键/唯一索引等值查询,最多1行WHERE id = 1、WHERE pk IN (1)⭐⭐⭐⭐⭐
eq_ref唯一索引关联,每行最多匹配1行JOIN 时被驱动表用主键/唯一索引关联⭐⭐⭐⭐
ref普通索引等值查询,可能多行WHERE idx_col = 'value'⭐⭐⭐⭐
fulltext全文索引检索MATCH() AGAINST()⭐⭐⭐
ref_or_nullref + NULL 值比较WHERE col = 1 OR col IS NULL⭐⭐⭐
index_merge使用多个索引取并集/交集WHERE a=1 OR b=2 且 a、b 各有索引⭐⭐⭐
unique_subqueryIN 子查询返回不重复值WHERE id IN (SELECT pk FROM t2)⭐⭐⭐
index_subqueryIN 子查询可能返回重复值WHERE id IN (SELECT col FROM t2)⭐⭐
range索引范围扫描WHERE id BETWEEN 1 AND 10、>、<、IN、LIKE 'prefix%'⭐⭐
index全索引扫描遍历整个索引树,不回表
ALL🔴 全表扫描未使用任何索引⭐(必须优化!)

🎯 优化目标:至少达到 range 级别,最好达到 ref 或 const,坚决杜绝 ALL

📐 key_len 计算规则

数据类型占用字节
TINYINT1
SMALLINT2
MEDIUMINT3
INT4
BIGINT8
FLOAT/DOUBLE4/8
DATE3
TIMESTAMP4
DATETIME8
CHAR(n) UTF83n
VARCHAR(n) UTF83n + 2(长度前缀)+ 1(NULL标识,如可为NULL)
CHAR(n) UTF8MB44n
VARCHAR(n) UTF8MB44n + 2 + 1(可为NULL时)

示例:VARCHAR(100) UTF8 可为NULL → 100 × 3 + 2 + 1 = 303 字节

💡 key_len 越短说明联合索引用的列越少,可判断索引是否生效

三、Extra 额外信息(⭐ 性能"晴雨表")

含义优化建议
✅ Using index覆盖索引,无需回表理想状态,保持!
⚠️ Using whereWHERE 过滤正常场景,无需特别优化
🔴 Using filesort无法用索引排序,需额外排序(内存/磁盘)给 ORDER BY 列加索引
🔴 Using temporary使用临时表(GROUP BY / DISTINCT 等)给分组/去重列加索引
✅ Using index condition索引条件下推(ICP,MySQL 5.6+)优化特性,无需处理
⚠️ Using join buffer使用连接缓冲区(BNL/BKA)给 JOIN 条件加索引
🟢 Select tables optimized away聚合函数通过索引直接返回如 SELECT MAX(id) FROM t
🔴 Impossible WHEREWHERE 条件恒假检查业务逻辑
🔴 Range checked for each record逐行检查索引,极差必须加索引

四、实战分析示例

EXPLAIN SELECT u.name, o.order_id
FROM users u
JOIN orders o ON u.id = o.user_id
WHERE u.age > 18
ORDER BY u.create_time DESC
LIMIT 10;
问题EXPLAIN 特征优化方案
全表扫描type=ALL, key=NULL为 age 字段加索引
排序未用索引Extra=Using filesort为 create_time 加索引
未用覆盖索引无 Using index建复合索引 (age, create_time, name)
临时表Extra=Using temporary优化 GROUP BY 或用覆盖索引

五、一句话总结优先级

看 type(至少 range) → 看 key(不能 NULL)→ 看 rows(越小越好)
→ 看 Extra(消除 filesort/temporary,追求 Using index)

到此这篇关于MySQL EXPLAIN 字段使用小结的文章就介绍到这了,更多相关MySQL EXPLAIN 字段内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文