mysql中explain的具体实现

 更新时间:2026年03月16日 10:13:43   作者:爱吃鲨鱼辣椒  
EXPLAIN是MySQL中用于分析SQL执行计划的核心命令,它能告诉你 MySQL优化器会如何执行这条SQL,本文就来想详细的介绍了mysql中explain的具体实现,感兴趣的可以了解一下

一、MySQL EXPLAIN 是什么?

EXPLAIN 是 MySQL 中用于分析 SQL 执行计划的核心命令,它能告诉你 MySQL 优化器会如何执行这条 SQL(比如用什么索引、扫描多少行、连接方式等),是优化慢 SQL 的必备工具。

可以把它理解为:你写了一条 SQL 想让 MySQL 执行,EXPLAIN 会提前告诉你 MySQL 的“执行思路”—— 走哪条路、做哪些操作、效率怎么样,帮你找到 SQL 里的性能瓶颈。

二、基本用法

1. 语法

EXPLAIN + 你的SQL语句;
-- 示例
EXPLAIN SELECT * FROM user WHERE id = 1;

如果想查看更详细的执行计划(比如执行时的成本、临时表等),可以用:

EXPLAIN ANALYZE SELECT * FROM user WHERE id = 1; -- MySQL 8.0 及以上支持

2. 输出字段说明

执行 EXPLAIN 后会返回一个结果集,核心字段如下(新手先掌握这 8 个核心字段即可):

字段核心含义
idSQL 执行的顺序(子查询/联表时会有多个 id,数字越大越先执行)
select_type查询类型(比如简单查询、子查询、联表查询、衍生表等)
table本次执行涉及的表名
type访问类型(核心!判断性能的关键,从差到好:ALL < index < range < ref < eq_ref < const/system)
possible_keysMySQL 可能会选择的索引(候选索引)
keyMySQL 实际使用的索引(如果为 NULL,说明没用到索引)
rowsMySQL 预估要扫描的行数(数值越小越好)
Extra额外信息(比如 Using index 走覆盖索引、Using where 过滤条件、Using filesort 排序等)

三、核心字段详解(新手重点)

1. type(访问类型)

这是 EXPLAIN 中最重要的字段,直接反映 SQL 的性能层级,常见值从差到优排序:

  • ALL:全表扫描(最差!会遍历整个表),比如 SELECT * FROM user; 且无任何条件。
  • index:全索引扫描(比 ALL 好一点,但仍扫描整个索引),比如查询的字段都在索引里,但无过滤条件。
  • range:索引范围扫描(比如用 >、<、BETWEEN、IN 等),比如 SELECT * FROM user WHERE id BETWEEN 1 AND 10;。
  • ref:非唯一索引扫描(匹配多行),比如 SELECT * FROM user WHERE name = '张三';(name 是普通索引)。
  • eq_ref:唯一索引扫描(匹配一行),比如联表查询时用主键/唯一索引关联,SELECT * FROM user u JOIN order o ON u.id = o.user_id;。
  • const/system:查询结果能确定为一行(最优),比如用主键查询 SELECT * FROM user WHERE id = 1;。

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

  • 如果 key 为 NULL,说明 MySQL 没用到索引,大概率是 SQL 写得有问题(比如用了函数操作索引字段、条件不匹配索引等)。
  • 示例:如果 user 表的 id 是主键(默认索引),执行 EXPLAIN SELECT * FROM user WHERE id = 1;,key 列会显示 PRIMARY(主键索引名)。

3. Extra(关键提示)

  • Using index:走了“覆盖索引”(查询的字段都在索引里,无需回表查数据),性能极佳。

示例:user 表有索引 idx_name_age (name, age),执行 EXPLAIN SELECT name, age FROM user WHERE name = '张三';,Extra 会显示 Using index。

  • Using where:MySQL 会先扫描数据,再用 WHERE 条件过滤(如果同时有 Using index,说明先走索引再过滤)。
  • Using filesort:MySQL 需额外做排序(不是用索引排序),性能差,比如 SELECT * FROM user ORDER BY name; 但 name 无索引。
  • Using temporary:MySQL 需创建临时表(比如 GROUP BY 没用到索引),性能差,要优化。

四、实战示例

假设有一张 user 表,结构如下:

CREATE TABLE `user` (
  `id` int PRIMARY KEY AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `age` int,
  `gender` tinyint,
  INDEX `idx_name` (`name`) -- 普通索引
);

示例 1:全表扫描(差)

EXPLAIN SELECT * FROM user WHERE age = 20;
  • type:ALL(全表扫描)
  • key:NULL(没用到索引)
  • Extra:Using where(扫描后过滤)
  • 优化:给 age 加索引 ALTER TABLE user ADD INDEX idx_age (age);。

示例 2:使用索引(好)

EXPLAIN SELECT * FROM user WHERE name = '张三';
  • type:ref(非唯一索引扫描)
  • key:idx_name(用到了 name 的索引)
  • rows:预估扫描行数(比如 10 行,远小于全表行数)。

示例 3:覆盖索引(优)

EXPLAIN SELECT name FROM user WHERE name = '张三';
  • type:ref
  • key:idx_name
  • Extra:Using index(覆盖索引,无需回表)。

五、使用注意事项

  1. EXPLAIN 的 rows 是 MySQL 预估的扫描行数,不是实际行数,但能反映性能趋势(数值越小越好)。
  2. EXPLAIN 只分析执行计划,不会实际执行 SQL(除非用 EXPLAIN ANALYZE),所以可以放心在生产环境使用。
  3. 即使 possible_keys 有值,key 也可能为 NULL —— 说明 MySQL 认为走索引不如全表扫描快(比如表数据量极小)。

总结

  1. EXPLAIN 是分析 SQL 执行计划的核心工具,重点看 type(访问类型)、key(实际索引)、Extra(额外提示)三个字段。
  2. 优化目标:尽量让 type 达到 range 及以上,key 不为 NULL,避免 Extra 出现 Using filesort/Using temporary。
  3. 最理想的执行计划:type 为 const/system + key 有值 + Extra 显示 Using index。

到此这篇关于mysql中explain的具体实现的文章就介绍到这了,更多相关mysql explain内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mysql中的排序规则utf8_unicode_ci、utf8_general_ci的区别总结

    Mysql中的排序规则utf8_unicode_ci、utf8_general_ci的区别总结

    Mysql中utf8_general_ci与utf8_unicode_ci有什么区别呢?在编程语言中,通常用unicode对中文字符做处理,防止出现乱码,那么在MySQL里,为什么大家都使用utf8_general_ci而不是utf8_unicode_ci呢?
    2014-04-04
  • MySQL优化方案之开启慢查询日志

    MySQL优化方案之开启慢查询日志

    相信大家应该都知道MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,下面这篇文章主要给大家介绍了关于MySQL优化方案之开启慢查询日志的相关资料,需要的朋友可以参考下
    2021-12-12
  • 超简单的qps统计方法(推荐)

    超简单的qps统计方法(推荐)

    下面小编就为大家带来一篇超简单的qps统计方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-03-03
  • Mysql免安装版设置密码教程详解

    Mysql免安装版设置密码教程详解

    这篇文章主要介绍了Mysql免安装版设置密码教程详解,需要的朋友可以参考下
    2017-05-05
  • MySQL中大数据表增加字段的实现思路

    MySQL中大数据表增加字段的实现思路

    最近遇到的一个问题,需要在一张将近1000万数据量的表中添加加一个字段,但是直接添加会导致mysql 奔溃,所以需要利用其他的方法进行添加,这篇文章主要给大家介绍了MySQL中大数据表增加字段的实现思路,需要的朋友可以参考借鉴。
    2017-01-01
  • MySQL使用group by分组查询每组最新的一笔数据实现方式

    MySQL使用group by分组查询每组最新的一笔数据实现方式

    这篇文章主要介绍了MySQL使用group by分组查询每组最新的一笔数据实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-06-06
  • 同时运行多个MySQL服务器的方法

    同时运行多个MySQL服务器的方法

    在同一台机器上运行多个有些情况下你可能想要在同一台机器上运行多个服务器。例如,你可能想要测试一个新的MySQL版本而让你现有生产系统的设置不受到干扰, 或你可能是想要为不同的客户提供独立的MySQL安装一个因特网服务供应商。
    2008-05-05
  • 重置MySQL 8.0 Root密码的简便方法小结

    重置MySQL 8.0 Root密码的简便方法小结

    这篇文章主要给大家介绍了几种轻松重置 MySQL 8.0 Root 密码的简便方法,文中通过代码示例讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-10-10
  • navicat 连接数据库隔段时间后自动断开连接的解决方案

    navicat 连接数据库隔段时间后自动断开连接的解决方案

    这篇文章主要介绍了navicat 连接数据库隔段时间后自动断开连接的解决方案,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • DB为何大量出现select @@session.tx_read_only 详解

    DB为何大量出现select @@session.tx_read_only 详解

    这篇文章主要给大家介绍了关于DB为何大量出现select @@session.tx_read_only 的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-04-04

最新评论