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 | 简单查询,无子查询/UNION | SELECT * FROM t1 WHERE id=1 |
| PRIMARY | 最外层查询(含子查询时) | 包裹子查询的外层 SELECT |
| SUBQUERY | SELECT 或 WHERE 中的子查询 | SELECT * FROM t1 WHERE id IN (SELECT id FROM t2) |
| DEPENDENT SUBQUERY | 依赖外部查询的子查询 | 子查询引用了外层表的列 |
| DERIVED | FROM 子句中的子查询(派生表) | SELECT * FROM (SELECT * FROM t1) a |
| UNION | UNION 中第二个及之后的 SELECT | SELECT * FROM t1 UNION SELECT * FROM t2 |
| DEPENDENT UNION | 依赖外部查询的 UNION | UNION 子查询引用外层表 |
| UNION RESULT | UNION 的结果合并 | 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_null | ref + NULL 值比较 | WHERE col = 1 OR col IS NULL | ⭐⭐⭐ |
| index_merge | 使用多个索引取并集/交集 | WHERE a=1 OR b=2 且 a、b 各有索引 | ⭐⭐⭐ |
| unique_subquery | IN 子查询返回不重复值 | WHERE id IN (SELECT pk FROM t2) | ⭐⭐⭐ |
| index_subquery | IN 子查询可能返回重复值 | 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 计算规则
| 数据类型 | 占用字节 |
|---|---|
| TINYINT | 1 |
| SMALLINT | 2 |
| MEDIUMINT | 3 |
| INT | 4 |
| BIGINT | 8 |
| FLOAT/DOUBLE | 4/8 |
| DATE | 3 |
| TIMESTAMP | 4 |
| DATETIME | 8 |
| CHAR(n) UTF8 | 3n |
| VARCHAR(n) UTF8 | 3n + 2(长度前缀)+ 1(NULL标识,如可为NULL) |
| CHAR(n) UTF8MB4 | 4n |
| VARCHAR(n) UTF8MB4 | 4n + 2 + 1(可为NULL时) |
示例:VARCHAR(100) UTF8 可为NULL → 100 × 3 + 2 + 1 = 303 字节
💡 key_len 越短说明联合索引用的列越少,可判断索引是否生效
三、Extra 额外信息(⭐ 性能"晴雨表")
| 值 | 含义 | 优化建议 |
|---|---|---|
| ✅ Using index | 覆盖索引,无需回表 | 理想状态,保持! |
| ⚠️ Using where | WHERE 过滤 | 正常场景,无需特别优化 |
| 🔴 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 WHERE | WHERE 条件恒假 | 检查业务逻辑 |
| 🔴 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 字段内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
