菜单

Loen
发布于 2025-08-30 / 6 阅读
0
0

mysql 分析执行计划

完全不用担心!记不住 EXPLAIN 的输出字段是非常正常的,因为它包含的信息确实很多。这其实不是一个需要死记硬背的东西,而是一个需要理解其核心思想并通过查看来熟练使用的工具

下面我给您一个超实用的 “三步速查指南”核心字段详解,您以后遇到就翻出来看,看多了自然就熟了。

三步速查指南:如何快速判断SQL性能?

拿到一条 EXPLAIN 结果,不要一个个字段看晕了,按照这三个步骤来分析:


第一步:先看 type 列(访问类型)—— 这是最重要的指标!

这列告诉你 MySQL 如何查找数据。从好到坏排列,理想状态是尽量靠前:

类型 (值) 含义 性能 解读
system 系统表,只有一行数据 最佳 忽略,极少见。
const 通过主键或唯一索引一次就找到 极佳 WHERE id = 1,效率最高。
eq_ref 联表查询时,使用主键或唯一索引关联 极佳 常见于 A JOIN B ON A.id = B.id
ref 使用普通非唯一索引查找 优秀 WHERE name = 'Alice'(name是普通索引)。
range 索引范围扫描 良好 WHERE id > 100BETWEENIN
index 全索引扫描 较差 比全表扫描好点,但需要扫描整个索引树。
ALL 全表扫描 最差 警报! 性能杀手,需要优化。

您的例子解读:
type: ALL -> 这是最坏的情况,说明MySQL正在对 com_order 表进行全表扫描,性能极差。


第二步:看 keypossible_keys 列(用没用索引?)

  • possible_keys: 可能用到的索引(MySQL分析后认为可以用的索引列表)。
  • key: 实际用到的索引。如果为 NULL,说明没用到索引。

您的例子解读:
possible_keys: NULLkey: NULL -> 说明这条查询没有任何合适的索引可用,这完美解释了为什么第一步的 typeALL(全表扫描)。


第三步:看 rowsExtra 列(扫描了多少行?有没有额外操作?)

  • rows: MySQL 估算需要扫描的行数。这个值越小越好
    • 您的例子解读rows: 2356562 -> 预计要扫描235万行!这证实了性能问题非常严重。
  • Extra: 额外信息,非常重要,常包含优化建议。
    • Using where: 表示在存储引擎检索行后,MySQL服务器还需要再进行过滤。
    • Using index: (好信号) 表示查询只用了索引中的信息,无需回表。
    • Using temporary: (坏信号) 表示需要创建临时表来处理查询,常见于GROUP BY、ORDER BY。
    • Using filesort: (坏信号) 表示无法利用索引完成排序,需要额外的排序操作。

您的例子解读
Extra: Using where -> 结合全表扫描,说明MySQL从硬盘读出235万行数据后,还要在内存里一条条用你的WHERE条件去过滤。


对您这条SQL的综合分析与优化建议

结论:这是一条非常糟糕的查询,急需优化。

  1. 问题根源WHERE 条件中的列没有建立索引,导致数据库只能进行全表扫描。
  2. 性能影响:每次查询需要扫描约 235万行 数据,CPU和磁盘I/O压力巨大,速度极慢。

解决方案:为 WHERE 条件中的列添加索引

假设您的查询语句类似:

SELECT * FROM com_order WHERE your_column = 'some_value';

您需要为 your_column 创建索引:

ALTER TABLE com_order ADD INDEX idx_your_column (your_column);

创建索引后,再使用 EXPLAIN 查看,您会看到神奇的变化:

  • type 会从 ALL 变为 ref(如果是等值查询)或 range(如果是范围查询)。
  • key 会显示 idx_your_column,表示正在使用您新创建的索引。
  • rows 会从一个巨大的数变成一个很小的数(例如1、10、100)。
  • 查询速度将会提升几十甚至几百倍。

总结:一张图记住核心流程

下次分析 EXPLAIN,就按这个顺序看:

flowchart TD
A[拿到EXPLAIN结果] --> B{"第一步:看type字段"}
B --✅ const, eq_ref, ref, range --> E[✅ 性能良好]
B --⚠️ index --> F[⚠️ 有待优化]
B --❌ ALL --> C["❌ 警报!全表扫描"]

C --> D{"第二步:看key字段"}
D --NULL--> G["确认:无索引可用<br>解决方案:为WHERE条件列创建索引"]
D --有值--> H["异常:有索引却未使用<br>解决方案:检查索引是否失效<br>或查询写法问题"]

E --> I["第三步:看rows和Extra"]
I --> J["rows: 估算行数越少越好<br>Extra: 警惕Using filesort/temporary"]

评论