MySQL EXPLAIN从执行计划到索引优化完全解读

 更新时间:2026年07月10日 09:14:40   作者:华章酱  
EXPLAIN执行计划是MySQL性能优化的核心工具,其本质是通过解析SQL语句的执行路径,揭示数据库引擎的决策逻辑,这篇文章主要介绍了MySQL EXPLAIN从执行计划到索引优化的相关资料,需要的朋友可以参考下

前言

在 MySQL 数据库调优中,EXPLAIN 是开发者最强大的“照妖镜”。任何 SELECT 查询,只要在前面加上 EXPLAIN,MySQL 就会告诉你它打算怎么执行这条 SQL——用哪些索引、联表顺序、扫描多少行、有没有隐性问题。

本文将从实际开发视角,逐一拆解 EXPLAIN 输出中的每个字段,并给出可直接落地的优化判断标准。

一、EXPLAIN 是什么?

执行 EXPLAIN SELECT ... 后,MySQL 不会真实执行查询,而是返回执行计划,以表格形式展示每一步如何操作。

EXPLAIN SELECT * FROM user WHERE id = 1;

输出一行或多行,每一行代表一个步骤(单表访问、子查询、UNION 等)。

二、字段详解(按重要性排序)

1. id —— 步骤编号

  • 数字越大,越先执行

  • 数字相同,从上往下执行

  • NULL:最后合并步骤(如 UNION)

子查询不一定比主查询后执行,DERIVED 表反而先执行。

2. select_type —— 查询类型

含义性能警示
SIMPLE简单查询,无子查询、无UNION✅ 正常
PRIMARY外层主查询-
SUBQUERY普通子查询⚠️ 可能慢
DERIVEDFROM 中的子查询(派生表)⚠️ 一般慢
UNIONUNION 中第二个及之后的查询⚠️
DEPENDENT SUBQUERY相关子查询(依赖外层)❌ 极慢,必须改 JOIN
UNCACHEABLE SUBQUERY每次执行都要重算❌ 极慢

重点关注DEPENDENT SUBQUERY 是性能杀手,几乎都应改写为 JOIN。

3. table —— 访问对象

可以是真实表名,也可能是 <derived2>(id=2 的派生表)或 <union1,2>

4. type —— 访问类型 ★★★★

最重要的字段之一,直接反映索引使用效率。性能从好到差

级别含义说明
system表只有一行系统表,极少见
const主键/唯一索引等值查询极快,最多匹配一行
eq_ref联表时被驱动表用主键/唯一索引联表最优
ref普通索引等值查询
range索引范围查询(>, <, IN, BETWEEN)尚可
index扫描整个索引树比全表快一点,但仍需回表
ALL全表扫描❌ 最差,大表必崩

优化红线type = ALL 且表数据量 > 10万行,必须加索引

5. possible_keys —— 可能使用的索引

列出候选索引。若为 NULL,说明该表无可用索引,必须创建。

6. key —— 实际使用的索引 ★★★★

  • 为 NULL:没走索引

  • 需与 possible_keys 对比:有时明明有索引,MySQL 却不选(原因见 Extra)

7. key_len —— 使用的索引长度(字节)

关键作用:判断联合索引用到了几列

示例:联合索引 (a, b, c)

  • key_len = 4:只用到了 a(INT)

  • key_len = 8:用到了 a、b(均为 INT)

  • key_len = 13:用到了 a、b、c(INT + INT + VARCHAR(10))

常见类型长度参考(utf8mb4):

  • INT:4 字节

  • BIGINT:8

  • VARCHAR(100):100 * 4 + 2 = 402 字节

  • DATETIME:5(5.6+)、8(旧版)

8. ref —— 与索引比较的对象

  • const:常量(如 WHERE id = 1

  • db.table.column:联表时的另一张表列

  • NULL:不是等值查询

9. rows —— 预计扫描行数 ★★★★

MySQL 估算值,非精确数值越大,查询越慢。优化目标就是让 rows 持续变小。

10. filtered —— 过滤后剩余比例(%)

存储引擎返回后,经过 WHERE 条件过滤还剩下的比例。越低越好,说明索引筛选能力强。

示例:rows = 1000, filtered = 10 → 预计最终返回 100 行。

11. Extra —— 额外信息 ★★★★★

最重要的补充说明直接暴露性能陷阱

好信号

含义
Using index覆盖索引,不回表,极快
Using where有 WHERE 条件过滤

警告信号(需优化)

含义处理建议
Using index condition索引条件下推(ICP)尚可,但可检查索引顺序
Using temporary用了临时表❌ GROUP BY 无索引,必须改
Using filesort文件排序(内存/磁盘)❌ ORDER BY 无索引,必须加
Using join buffer联表无索引,用缓存❌ 必须为被驱动表加索引

危险信号

含义
Using temporary; Using filesortGROUP BY + ORDER BY 完全没走索引
Impossible WHEREWHERE 条件永远为假
No tables used无 FROM 表

三、实战:5 分钟定位慢查询

拿到一条慢 SQL,按以下顺序逐列审查 EXPLAIN 结果:

第一步:先看type

  • ✅ const/eq_ref/ref → 安全

  • ⚠️ range → 尚可

  • ❌ index/ALL → 必须优化

第二步:再看key

  • 为 NULL → 没索引,立即加

  • 不为 NULL → 检查是否选对了索引

第三步:看Extra

  • 出现 filesort/temporary/join buffer → 必须优化

  • 出现 Using index → 优秀

第四步:估算rows

  • 预期只返回几条,但 rows 显示几万 → 索引失效或没走对索引

四、典型案例优化全过程

原始慢查询

EXPLAIN 
SELECT * FROM order 
WHERE user_id = 123 
ORDER BY create_time DESC;

执行计划

  • typeALL(全表扫描)

  • rows: 500000

  • ExtraUsing filesort(文件排序)

  • key: NULL

结论:全表扫 50 万行,再在内存排序 → 极慢

添加索引

ALTER TABLE order ADD INDEX idx_user_time (user_id, create_time);

优化后执行计划

EXPLAIN 
SELECT * FROM order 
WHERE user_id = 123 
ORDER BY create_time DESC;
  • typeref(走索引)

  • key: idx_user_time

  • rows: 15

  • ExtraUsing index condition(无 filesort)

效果:50万行扫描 → 15行,排序消失。

五、总结:EXPLAIN 优化口诀

EXPLAIN 看计划,逐行拆开查:
type 是关键,ALL 是红线;
key 不为空,才算走索引;
rows 尽量小,越大越危险;
Extra 藏魔鬼,temporary 必须改,filesort 立即办;
覆盖索引最理想,Using index 放心赞。

写在最后

EXPLAIN 是 MySQL 性能优化的入场券。掌握它,你就能在索引设计、SQL 改写、架构选型上拥有判断力。

但 EXPLAIN 不是万能的:

  • 它是估算,不是精确值

  • 不统计存储引擎外的消耗(网络、客户端)

  • 不反映锁等待、CPU 开销

因此,EXPLAIN + 慢查询日志 + 性能监控,才是完整的 MySQL 调优体系。

到此这篇关于MySQL EXPLAIN从执行计划到索引优化完全解读的文章就介绍到这了,更多相关MySQL EXPLAIN详解内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL数据库修复方法(MyISAM/InnoDB)

    MySQL数据库修复方法(MyISAM/InnoDB)

    这篇文章主要为大家整理了7条修复MySQL数据库的方法,当简单的重启对数据库不起作用,或者有表崩溃时,需要的朋友可以参考下
    2014-06-06
  • 一文带你了解MySQL之约束

    一文带你了解MySQL之约束

    在SQL标准中,一共规定了6种不同的约束,包括非空约束,唯一约束和检查约束等,而在MySQL中是不支持检查约束的,所以这篇文章先对其余5种约束做一个详解和练习,需要的朋友可以参考下
    2023-06-06
  • linux下讲解MySQL安装与登录方法

    linux下讲解MySQL安装与登录方法

    MySQL安装文件已被广泛应用但是也在不断的更新,这里介绍MySQL安装文件设置使用,帮助大家安装更新MySQL安装文件系统。
    2010-11-11
  • MySQL sum后再计算percentage的多种解决办法

    MySQL sum后再计算percentage的多种解决办法

    这篇文章主要介绍了MySQL sum后再计算percentage的多种解决办法,over() 函数,Cross Join,Select 嵌套查询以及 with 函数处理,文中通过代码示例讲解的非常详细,需要的朋友可以参考下
    2024-06-06
  • mysql 8.0.19 win10快速安装教程

    mysql 8.0.19 win10快速安装教程

    这篇文章主要为大家详细介绍了mysql 8.0.19 win10快速安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • MySQL中ADD COLUMN添加多个字段的写法实例

    MySQL中ADD COLUMN添加多个字段的写法实例

    这篇文章主要给大家介绍了关于MySQL中ADD COLUMN添加多个字段的写法实例,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2023-02-02
  • mysql SELECT语句去除某个字段的重复信息

    mysql SELECT语句去除某个字段的重复信息

    mysql SELECT语句去除某个字段的重复信息,需要的朋友可以收藏下。
    2010-04-04
  • MySQL中的binary类型使用操作

    MySQL中的binary类型使用操作

    这篇文章主要介绍了MySQL中的binary类型使用操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • 一文带你深入了解并掌握MySQL的DML和DCL

    一文带你深入了解并掌握MySQL的DML和DCL

    在数据库管理中,数据操作语言(DML)和数据控制语言(DCL)是至关重要的概念,DML使我们能够对数据库中的数据进行增加、修改和删除操作,本文将深入探讨这两个关键领域的核心概念和操作方法,帮助您更好地理解和应用数据库管理技术
    2024-02-02
  • 详解MySQL中的事务与ACID特性

    详解MySQL中的事务与ACID特性

    这篇文章主要为大家介绍了Mysql 中的事务,包括事务的基本概念和 ACID 特性、事务的隔离级别和具体实现方法等,并提供相应的代码示例,希望对大家有所帮助
    2023-05-05

最新评论