MySQL EXPLAIN语法使用超详细详解

 更新时间:2026年07月28日 09:10:19   作者:更容易记住我  
EXPLAIN作为MySQL的性能分析神器,读懂其结果是很有必要的,然而我在各种搜索引擎上竟然找不到特别完整的解读,这篇文章主要介绍了MySQL EXPLAIN语法使用的相关资料,需要的朋友可以参考下

引言

EXPLAIN 是 MySQL SQL 优化神器,用来查看 MySQL 执行计划,能清晰看到 MySQL 如何执行你的查询、是否使用索引、表关联顺序、数据扫描行数等,是排查慢查询、优化 SQL 的核心工具。

一、基础用法

1. 标准语法

-- 直接加在 SELECT/DELETE/UPDATE/INSERT 语句前面
EXPLAIN SELECT * FROM user WHERE id = 1;

-- 查看更详细的执行计划(推荐使用)
EXPLAIN ANALYZE SELECT * FROM user WHERE id = 1; -- MySQL 8.0.18+ 支持

2. 能查什么?

  • 表的读取顺序
  • 表的读取类型(是否高效)
  • 索引是否命中、命中哪个索引
  • 扫描的数据行数
  • 数据过滤比例
  • 表之间的关联方式

二、执行计划字段全解

执行 EXPLAIN 后会返回一张表,共 12+ 个关键字段,下面是最核心、必须掌握的字段:

1. id(查询执行顺序)

表示查询中执行 select 子句或操作表的顺序。

  • id 相同:执行顺序从上到下
  • id 不同:id 越大优先级越高,越先执行
  • id 为 NULL:表示这是一个结果集,无需执行

2. select_type(查询类型)

判断查询是简单查询还是复杂查询:

含义
SIMPLE简单查询(不包含子查询、union)
PRIMARY复杂查询中最外层的查询
SUBQUERY子查询(select 里面嵌套的查询)
DERIVED派生表(from 子句中的子查询)
UNIONunion 中的第二个及后面的查询
UNION RESULTunion 的结果集

3. table(涉及的表)

显示这一行数据是关于哪张表的。

  • 可能是表名
  • 可能是别名
  • 可能是 <derivedN>/<unionM,N>(临时表)

4. type(访问类型 → 核心!)

SQL 优化最重要的指标,表示 MySQL 在表中找到数据的方式,性能从好到坏排序:

system > const > eq_ref > ref > range > index > ALL

优化目标:至少达到 range,最好 ref 及以上

各类型详解

  • system:表只有一行数据(系统表),极致性能
  • const:通过主键 / 唯一索引精确匹配一行数据(如 WHERE id=1)
  • eq_ref:多表关联时,主键 / 唯一索引关联,每次只匹配一行
  • ref:普通索引匹配,找到多个符合条件的行(最常见的优化目标)
  • range:索引范围查询(>、<、between、in、like 前缀匹配)
  • index:遍历整个索引树(比全表快,但仍需优化)
  • ALL:全表扫描(最差!必须优化)

5. possible_keys(可能用到的索引)

MySQL 认为可能会用于查询的索引,但最终不一定使用。

  • 为 NULL:无可用索引
  • 显示多个索引:MySQL 会从中选最优的一个

6. key(实际使用的索引)

真正命中的索引,优化核心看这个字段!

  • 为 NULL:没有使用索引(严重问题)
  • 显示索引名:使用了该索引

7. key_len(使用的索引长度)→ 超详细计算规则

key_len 表示 MySQL 实际使用的索引字节长度,用来判断:

  • 联合索引用了几列
  • 索引是否充分利用
  • 字段是否允许 NULL、是否变长

计算核心公式

key_len = 字段实际字节数 + NULL标记(1字节) + 变长字段长度(2字节)

一、基础数据类型字节数

先记住常用字段固定字节:

字段类型字节数说明
tinyint1-128~127
smallint2小整数
int4普通整数
bigint8长整数
float4单精度
double8双精度
char(n)n × 字符集字节定长字符串
varchar(n)n × 字符集字节变长字符串
date3日期
datetime8日期时间
timestamp4时间戳

字符集占用字节

  • utf8:1 字符 = 3 字节
  • utf8mb4:1 字符 = 4 字节
  • gbk:1 字符 = 2 字节
  • latin1:1 字符 = 1 字节

二、3 个额外规则(必记)

  1. 允许 NULL → +1 字节
    字段定义 DEFAULT NULL,索引会多 1 字节标记 NULL。
  2. 变长字段(varchar/varbinary)→ +2 字节
    用来存储字符串长度。
  3. 联合索引 → 多列累加计算

三、实战计算案例(一看就会)

案例 1:int 类型

age int NOT NULL        -- 索引

key_len = 4(int)+ 0(not null)= 4

age int NULL            -- 索引

key_len = 4 + 1(NULL)= 5

案例 2:char 固定字符串

name char(10) NOT NULL  utf8mb4

key_len = 10×4 + 0 = 40

name char(10) NULL      utf8mb4

key_len = 10×4 + 1 = 41

案例 3:varchar 变长字符串(最常用)

phone varchar(20) NOT NULL   utf8mb4

key_len = 20×4 + 2(变长)= 82

phone varchar(20) NULL       utf8mb4

key_len = 20×4 + 2 + 1 = 83

案例 4:联合索引(判断用了几列)
表结构:

idx_age_name(age int, name varchar(10))
age int NOT NULL
name varchar(10) NULL  utf8mb4
  • 只用到 age:key_len = 4
  • 用到 age + name:4 + (10×4 +2 +1) = 4+43=47

看到 key_len=47 → 说明联合索引两列都用上了!

四、快速计算速查表

字段定义key_len
int not null4
int null5
bigint not null8
bigint null9
varchar(20) not null utf8mb420×4+2=82
varchar(20) null utf8mb420×4+2+1=83
char(10) not null utf830
char(10) null utf831

五、key_len 核心用途(优化必用)

  1. 判断联合索引是否用满
    联合索引 idx(a,b,c)
    key_len 小 → 只用了前面 1~2 列
    key_len 大 → 全部列都命中
  2. 判断是否因为 NULL 浪费空间
  3. 判断索引是否精准命中

总结

  • 固定类型:直接字节数
  • 允许 NULL:+1
  • 变长字段:+2
  • 字符串:字符数 × 字符集字节
  • 联合索引:多列累加

8. ref(与索引比较的列)

显示哪个列 / 常量和索引比较,找到匹配的数据。

示例:const(常量匹配)、库名.表名.列名

9. rows(扫描行数)

MySQL 预估要扫描读取的数据行数。

  • 数值越小越好
  • 全表扫描时,这个值会非常大

10. Extra(额外重要信息)

包含很多关键优化提示,重点关注:

含义 & 优化建议
Using index✅ 覆盖索引!查询的字段刚好在索引里,无需回表(最优)
Using where使用 WHERE 条件过滤数据
Using filesort❌ 文件排序!MySQL 无法用索引排序,需额外排序(必须优化)
Using temporary❌ 使用临时表!常见于 group by /order by(必须优化)
Impossible WHEREWHERE 条件永远不成立(无意义查询)

三、实战案例:看懂执行计划

案例 1:主键查询(最优)

EXPLAIN SELECT * FROM user WHERE id = 1;

结果

  • type: const
  • key: PRIMARY
  • Extra: 无额外信息

✅ 完美,直接命中主键索引

案例 2:普通索引查询

EXPLAIN SELECT name FROM user WHERE phone = '13800138000';

结果

  • type: ref
  • key: idx_phone
  • Extra: Using index

✅ 优秀,覆盖索引,无需回表

案例 3:全表扫描(最差)

EXPLAIN SELECT * FROM user WHERE age = 20;

结果

  • type: ALL
  • key: NULL
  • rows: 10000

❌ 严重问题,全表扫描,必须给 age 加索引

案例 4:索引失效(文件排序)

EXPLAIN SELECT * FROM user ORDER BY address;

结果

  • Extra: Using filesort

❌ 必须给 address 加索引优化排序

四、索引失效常见场景(用 EXPLAIN 快速判断)

执行计划中 key=NULL 就是索引失效,常见原因:

1. 索引列上使用函数 / 运算

-- 失效
SELECT * FROM user WHERE YEAR(create_time) = 2024;

2. 模糊查询以 % 开头

-- 失效
SELECT * FROM user WHERE name LIKE '%张三';

3. 类型隐式转换(字符串不加引号)

-- 失效(phone 是字符串,没加引号)
SELECT * FROM user WHERE phone = 13800138000;

4. 使用 NOT IN、!=、IS NOT NULL 等

5. 联合索引不满足最左前缀原则

五、EXPLAIN 使用总结(速记)

  1. 看 type:至少达到 range,优先 ref
  2. 看 key:必须有索引,不能为 NULL
  3. 看 rows:扫描行数越少越好
  4. 看 Extra:严禁 Using filesort、Using temporary
  5. 加索引:全表扫描、索引失效时优先加合适索引

总结

EXPLAIN 是 MySQL 优化必用工具,核心看执行计划最重要指标:type(访问类型)、key(实际索引)、Extra(额外信息)

优化目标:避免全表扫描、文件排序、临时表,尽量使用覆盖索引

8.0+ 推荐用 EXPLAIN ANALYZE,能看到实际执行时间,优化更精准

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

相关文章

  • MySQL创建用户以及用户权限详细图文教程

    MySQL创建用户以及用户权限详细图文教程

    在MySQL中可以通过创建用户来管理数据库的访问权限,下面这篇文章主要给大家介绍了关于MySQL创建用户以及用户权限的相关资料,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • MySQL系列之十一 日志记录

    MySQL系列之十一 日志记录

    这篇文章主要介绍了MySQL日志文件详解,本文分别讲解了错误日志、二进制日志、通用查询日志、慢查询日志、Innodb的在线redo日志、更新日志等日志类型和作用介绍,需要的朋友可以参考下
    2021-07-07
  • mysql报错:Deadlock found when trying to get lock; try restarting transaction的解决方法

    mysql报错:Deadlock found when trying to get lock; try restarti

    这篇文章主要给大家介绍了关于mysql出现报错:Deadlock found when trying to get lock; try restarting transaction的解决方法,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • mysql 5.7.17的最新安装教程图文详解

    mysql 5.7.17的最新安装教程图文详解

    mysql-5.7.17-winx64是现在最新版本的Mysql,这是免安装的,所以要进行些配置,下面通过本文给大家介绍mysql 5.7.17的最新安装教程图文详解,感兴趣的朋友一起学习吧
    2017-03-03
  • MySQL之多表查询自连接方式

    MySQL之多表查询自连接方式

    这篇文章主要介绍了MySQL之多表查询自连接方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-09-09
  • MySQL JSON类型的功能与应用

    MySQL JSON类型的功能与应用

    MySQL8的JSON数据类型为存储和查询JSON数据提供了强大的支持,本文主要介绍了MySQL JSON类型的功能与应用,具有一定的参考价值,感兴趣的可以了解一下
    2024-08-08
  • MySQL事务(transaction)看这篇就足够了

    MySQL事务(transaction)看这篇就足够了

    M事务的实现是基于数据库的存储引擎,不同的存储引擎对事务的支持程度不一样,下面这篇文章主要给大家介绍了关于MySQL事务(transaction)的相关资料,需要的朋友可以参考下
    2022-11-11
  • MySQL复合查询和表的内外连接示例详解

    MySQL复合查询和表的内外连接示例详解

    在数据库管理和数据分析中,单表查询往往无法满足复杂的数据查询需求,因此多表查询和子查询成为了解决问题的关键技术,MySQL支持多种多表查询方式,如内连接、外连接(左外连接和右外连接)以及自连接,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • mysql下float类型使用一些误差详解

    mysql下float类型使用一些误差详解

    我想很多朋友都不怎么会在mysql中使用float类型,特别是用到金钱时我们可能会用双精度来做,我们知道mysql的float类型是单精度浮点类型不小心就会导致数据误差
    2012-11-11
  • MySQL参数innodb_force_recovery详解

    MySQL参数innodb_force_recovery详解

    innodb_force_recovery是InnoDB存储引擎的一个重要参数,用于在数据库崩溃恢复时控制恢复行为的级别,下面就来详细的介绍一下,具有一定的参考价值,感兴趣的可以了解一下
    2025-07-07

最新评论