当前位置: 首页 > backend >正文

MySQL慢查询分析工具:EXPLAIN

概述

  • EXPLAIN 是 MySQL 中用于分析 SQL 查询执行计划的工具,能够帮助开发者理解查询的执行过程、索引使用情况、潜在性能瓶颈等。以下是 EXPLAIN 的详细解析及示例。
  • 文章已经整理成PDF电子书,喜欢的朋友可以转存以下,方便查看:https://pan.quark.cn/s/f52968c518d3

一、EXPLAIN 输出字段详解

字段说明
id查询的序列号,表示执行顺序。相同 id 按顺序执行,不同 id 从大到小执行。子查询或 UNION 会生成不同 id。
select_type查询类型:
- SIMPLE:简单查询(无子查询或 UNION)
- PRIMARY:最外层查询
- SUBQUERY:子查询
- DERIVED:派生表(FROM 子句中的子查询)
- UNION:UNION 中的第二个或后续查询
- UNION RESULT:UNION 结果合并
table当前行操作的表名(或别名),如派生表显示 <derivedN>(N 为子查询 id)。
partitions匹配的分区(若表未分区则为 NULL)。
type访问类型(性能关键指标):
- system:系统表(仅一行)
- const:通过主键或唯一索引匹配一行
- eq_ref:JOIN 时使用主键或唯一索引
- ref:非唯一索引扫描
- range:范围扫描(BETWEEN、IN 等)
- index:全索引扫描
- ALL:全表扫描
possible_keys可能使用的索引。
key实际使用的索引。
key_len使用的索引字节数,可判断是否使用完整索引。
ref与索引比较的列或常量(如 consttable.column)。
rows预估需要扫描的行数(越小越好)。
filtered返回结果占扫描行数的百分比(越高越好)。
Extra额外信息:
- Using where:使用 WHERE 过滤
- Using index:覆盖索引(无需回表)
- Using temporary:使用临时表
- Using filesort:额外排序(需优化)

二、EXPLAIN 示例分析

示例 1:简单查询(主键查询)

EXPLAIN SELECT * FROM users WHERE id = 1;

输出:

idselect_typetabletypekeyrowsExtra
1SIMPLEusersconstPRIMARY1Using where

分析:
type=const:通过主键直接定位到一行。

key=PRIMARY:使用主键索引。

rows=1:仅扫描一行,效率极高。


示例 2:全表扫描(无索引)

EXPLAIN SELECT * FROM orders WHERE total_amount > 100;

假设 total_amount 无索引:

idselect_typetabletypepossible_keyskeyrowsExtra
1SIMPLEordersALLNULLNULL10000Using where

分析:
type=ALL:全表扫描,性能差。

rows=10000:扫描所有行。

• 优化建议:为 total_amount 添加索引。


示例 3:联合索引(最左前缀原则)

-- 索引为 (country, city)
EXPLAIN SELECT * FROM addresses WHERE country = 'US' AND city = 'New York';

输出:

idselect_typetabletypekeyrowsExtra
1SIMPLEaddressesrefidx_country_city50Using where

分析:
key=idx_country_city:使用联合索引。

key_len:可计算是否用到了 countrycity 列。

若查询仅使用 city(不满足最左前缀):

EXPLAIN SELECT * FROM addresses WHERE city = 'New York';

此时 possible_keys 可能为 NULL,导致全表扫描。


示例 4:JOIN 查询

EXPLAIN SELECT u.name, o.order_date FROM users u JOIN orders o ON u.id = o.user_id WHERE u.age > 30;

输出:

idselect_typetabletypekeyrowsExtra
1PRIMARYurangeage_idx200Using where; Using index
1PRIMARYorefuser_id5Using where

分析:
u 表使用 age_idx 索引进行范围扫描,返回 200 行。

o 表通过 user_id 索引关联,每行 u 扫描 5 行 o 数据。

• 优化建议:确保 user_id 有索引,减少关联查询的行数。


示例 5:子查询与派生表

EXPLAIN SELECT * FROM (SELECT user_id FROM orders WHERE total_amount > 100) AS sub JOIN users ON sub.user_id = users.id;

输出:

idselect_typetabletypekeyrowsExtra
1PRIMARYALLNULL1000Using where
1PRIMARYuserseq_refPRIMARY1Using index
2DERIVEDordersrangeamount_idx1000Using index condition

分析:
• 子查询生成派生表 <derived2>,使用 amount_idx 索引扫描 1000 行。

• 主查询通过 eq_ref(主键)关联 users 表。


三、优化建议

  1. 避免全表扫描(type=ALL):为 WHERE 条件或 JOIN 字段添加索引。
  2. 利用覆盖索引(Using index):尽量让查询仅通过索引返回数据。
  3. 减少 Using filesortUsing temporary:优化 ORDER BY 和 GROUP BY,确保使用索引排序。
  4. 关注 rowsfiltered:若 rows 过大或 filtered 过低,需检查索引有效性。
  5. 调整 JOIN 顺序:让小表驱动大表,减少关联行数。

通过 EXPLAIN 分析执行计划,可以精准定位性能瓶颈,针对性优化 SQL 和索引设计。

http://www.xdnf.cn/news/2637.html

相关文章:

  • Awesome-Embodied-AI:具身AI机器人领域最全资源汇总(含人形机器人,多足机器人,灵巧手等精选资源)
  • C++11线程间通信同步与Linux中MySQL连接池实现
  • XLSX.utils.sheet_to_json设置了blankrows:true,但无法获取到开头的空白行
  • JDBC 使用流程详解
  • rag增强检索-基于关键词检索的混合检索模式
  • vue响应式原理——vue2和vue3的响应式实现区别
  • 非结构化数据解析
  • wsl(8) -- 图形界面
  • 封装el-autocomplete,接口调用
  • Ubuntu安装brew
  • OSI 模型(开放系统互联模型)
  • FEKO许可安装
  • CCF推荐学术会议-C(网络与信息安全):SAC 2025
  • Python学习之路(六)-图像识别
  • 数字化转型的未来趋势:从工具到生态,聚焦生态合作、绿色转型与全球化布局
  • Vue3 Element Plus el-tabs数据刷新方法
  • 更快的图像局部修改与可控生成:Flex.2-preview
  • 航顺 芯片 开发记录 (一) 2025年4月27日19:23:32
  • 【博客系统】博客系统第二弹:实现博客列表接口
  • T检验、F检验及样本容量计算学习总结
  • 通过示例学习:连续 XOR
  • SpringBoot驾校报名小程序实现
  • 详细PostMan的安装和基本使用方法
  • 【SF】在 Android 显示系统中,图层合成方式 Device 和 Client 的区别
  • 文章记单词 | 第50篇(六级)
  • Zookeeper HA集群搭建
  • 昂瑞微蓝牙OM6621系列对比选型指南
  • 《代码整洁之道》第8章 边界 - 笔记
  • NCCL 通信与调试
  • Grok发布了Grok Studio 和 Workspaces两个强大的功能。该如何使用?如何使用Grok3 API?