优化SQL:如何使用 EXPLAIN

EXPLAIN是优化SQL查询不可或缺的工具。掌握其输出结果中 typeExtra列的含义,是定位性能问题的关键。通常的优化路径是:避免出现 ALL类型的全表扫描,并通过创建合适的索引来将查询类型提升到 refrange,同时留意 Extra列中是否有 Using temporaryUsing filesort等需要优化的提示。

下面这个表格汇总了使用 EXPLAIN时返回结果中各字段的核心含义。

字段 含义与解读要点
**id**​ SELECT 查询的序列号。id值越大,执行优先级越高;id相同,则从上往下执行
**select_type**​ 查询的类型,例如简单查询(SIMPLE)、主查询(PRIMARY)、子查询(SUBQUERY)、派生表查询(DERIVED)等。
**type**​ 访问类型 ,即MySQL决定如何查找表中的行。这是判断查询效率的关键指标,从优到劣常见的有:const/eq_ref> ref> range> index> ALL(全表扫描,需要优化)。
**possible_keys**​ 查询可能使用到的索引。
**key**​ 查询实际使用 到的索引。如果为 NULL,则表示未使用索引。
**key_len**​ 使用的索引字节数。可用于判断索引是否被完全利用。
**rows**​ MySQL 估算需要扫描的行数。通常数值越小越好。
**Extra**​ 包含查询执行的附加信息 。非常重要,常出现如 Using filesort(需要额外排序)、Using temporary(使用了临时表)等,都是需要关注的优化点。

如何使用 EXPLAIN

使用 EXPLAIN非常简单,只需在需要分析的 SQL 语句前加上 EXPLAIN关键字即可。从 MySQL 5.6.3 开始,它不仅可以分析 SELECT语句,还可以分析 DELETEINSERTREPLACEUPDATE语句。

复制代码
-- 基本用法
EXPLAIN SELECT * FROM your_table WHERE column_name = 'value';

-- 也可以使用 DESCRIBE 或 DESC,它们是 EXPLAIN 的同义词
DESCRIBE SELECT * FROM your_table;
DESC SELECT * FROM your_table;

在 MySQL 8.0 及更高版本中,还可以指定输出格式以获得更详尽或更直观的信息:

  • FORMAT=TRADITIONAL:默认格式,以表格形式展示。

  • FORMAT=JSON:提供非常详细的 JSON 格式信息,包含成本估算等更多数据。

  • FORMAT=TREE:MySQL 8.0.16 及以上版本可用,以树形结构展示执行过程,能清晰显示哈希连接等高级特性。

    -- 指定输出格式
    EXPLAIN FORMAT=JSON SELECT * FROM your_table;

此外,MySQL 8.0.18 引入了 EXPLAIN ANALYZE ,这是一个非常强大的功能。它不仅显示执行计划,还会实际执行该语句,并返回详细的执行时间、返回行数等实际运行数据,能更准确地评估性能。

复制代码
-- 使用 EXPLAIN ANALYZE 获取实际执行数据(MySQL 8.0.18+)
EXPLAIN ANALYZE SELECT * FROM your_table WHERE column_name = 'value';

重点字段详解与优化提示

  1. type 字段(核心性能指标)

    这是评估查询效率最重要的字段。应该致力于让查询的 type至少达到 range级别,最好能达到 ref

    • system/const:性能最佳。通常通过主键(PRIMARY KEY)或唯一索引(UNIQUE INDEX)进行等值查询时出现,表示只返回一行数据。

    • eq_ref:常见于多表关联查询,使用主键或唯一索引作为关联条件,对于前一张表的每一行,当前表只有一条记录与之匹配。

    • ref:使用普通索引进行查询,可能会返回多条匹配的记录。这是非常常见的、高效的索引使用方式。

    • range :使用了索引进行范围扫描(如 BETWEENIN><等)。

    • index:全索引扫描。虽然比全表扫描(ALL)好,因为它只遍历索引树,但如果索引很大,速度也可能较慢。

    • ALL全表扫描 。这意味着MySQL需要读取整个表来找到匹配的行。在数据量大的情况下,这是必须优化的信号。通常的解决方案是为查询条件创建合适的索引。

  2. Extra 字段(重要优化线索)

    这个字段提供了大量关于MySQL如何解析查询的额外信息。以下是一些需要特别注意的值:

    • Using index覆盖索引。表示查询的列都包含在索引中,无需回表读取数据行,性能非常好。

    • Using where:表示服务器在存储引擎检索行后进行了进一步的过滤。

    • Using temporary :表示MySQL为了执行查询创建了临时表 。这通常发生在排序(ORDER BY)和分组(GROUP BY)操作中,如果可能,应考虑通过索引来优化。

    • Using filesort :表示MySQL无法利用索引进行排序,需要额外的排序操作 。如果可能,应尝试为 ORDER BY子句创建合适的索引。

使用技巧与局限性

  • 结合 SHOW WARNINGS :在执行 EXPLAIN后,立即运行 SHOW WARNINGS;,可以查看优化器优化后的SQL语句,有时能提供更多线索。

  • 注意估算值EXPLAIN(不包括 ANALYZE)输出的 rows等字段是基于统计信息的估算值,并非精确值。

  • 局限性EXPLAIN不会考虑查询缓存的影响,也不能显示触发器、存储过程对查询的影响,并且它只解释查询过程,不执行查询(EXPLAIN ANALYZE除外)。

相关推荐
MC丶科5 小时前
【SpringBoot常见报错与解决方案】中文乱码?Spring Boot 统一解决前后端中文乱码问题(含 Postman 测试)!别再百度“加 UTF-8”了!
spring boot·后端·postman
今晚务必早点睡6 小时前
微服务改数据库密码后服务仍能访问?一次“看似异常、实则常见”的生产现象全解析
数据库·微服务·oracle
老师我太想进步了20267 小时前
cmd连接MySQL及相关查询
数据库·mysql
kk哥88998 小时前
如何快速掌握JavaSE的核心语法?
java
我是一只小青蛙8888 小时前
AVL树:平衡二叉搜索树原理与C++实战
java·jvm·面试
浩瀚地学8 小时前
【Java】JDK8的一些新特性
java·开发语言·经验分享·笔记·学习
XXOOXRT9 小时前
基于SpringBoot的加法计算器
java·spring boot·后端·html5
阿崽meitoufa9 小时前
JVM虚拟机:垃圾收集器和判断对象是否存活的算法
java·jvm·算法
我是苏苏9 小时前
C#高级:使用ConcurrentQueue做一个简易进程内通信的消息队列
java·windows·c#