EXPLAIN是MySQL中分析SQL执行效率、定位性能瓶颈的核心工具,它能模拟MySQL优化器的执行逻辑,输出SQL的执行计划详情,让我们清晰看到查询是否使用索引、走了哪个索引、是否全表扫描、表连接方式等关键信息。

优化SQL的前提是读懂执行计划,而EXPLAIN就是解读执行计划的唯一入口,本文将全面解析EXPLAIN的每一列含义,重点吃透优化中最需要关注的核心字段,让SQL优化有迹可循。

一、EXPLAIN基础使用

1. 使用语法

在需要分析的SELECT语句前直接添加EXPLAIN关键字即可,简单直接:

EXPLAIN + 待分析的SQL语句;

2. 执行示例

以下是多表关联查询的EXPLAIN执行结果,也是后续解析各字段的基础示例:

mysql> explain select * from user u1 left join user u2 on u1.id=u2.id where u1.name='wyh';
+----+-------------+-------+------------+--------+------------------+------------------+---------+----------------+------+----------+-------+
| id | select_type | table | partitions | type   | possible_keys    | key              | key_len | ref            | rows | filtered | Extra |
+----+-------------+-------+------------+--------+------------------+------------------+---------+----------------+------+----------+-------+
|  1 | SIMPLE      | u1    | NULL       | ref    | idx_name_address | idx_name_address | 1023    | const          |    1 |      100 | NULL  |
|  1 | SIMPLE      | u2    | NULL       | eq_ref | PRIMARY          | PRIMARY          | 8       | ssb_test.u1.id |    1 |      100 | NULL  |
+----+-------------+-------+------------+--------+------------------+------------------+---------+----------------+------+----------+-------+
2 rows in set

3. 核心关注字段

EXPLAIN输出的所有列都有其意义,但实际优化中,抓住5个核心字段就能解决90%的性能问题,重点关注:

  • id:查询的执行顺序
  • type:表的访问类型(核心中的核心,直接反映索引使用效率)
  • possible_keys:查询可命中的索引集合
  • key:优化器实际选中的索引(判断是否走对索引)
  • Extra:额外执行信息(反映是否有文件排序、临时表等性能损耗)

二、EXPLAIN各字段详细解析

1. id - 查询执行顺序标识

id表示SQL中各查询操作的执行优先级,数值为数字,核心规则:

  • id越大,执行顺序越靠前(子查询的id通常大于外层查询,先执行子查询再执行外层)
  • id相同,执行顺序从上到下(多表连接、同层级查询按结果集中的行序执行)

2. select_type - 查询类型

select_type用于区分普通查询、子查询、联合查询等不同的查询类型,核心标识查询的复杂程度,常见取值及含义:

  • SIMPLE:简单SELECT查询,查询中不包含子查询、UNION或其他复杂结构
  • PRIMARY:查询中包含复杂子部分时,最外层的查询会被标记为该类型
  • SUBQUERY:在SELECT子句或WHERE子句中直接包含的子查询
  • DERIVED:在FROM子句中包含的子查询,MySQL会将其执行结果存入临时衍生表
  • UNIONUNION关键字后第二个及之后的SELECT查询
  • UNION RESULT:从UNION联合查询的结果集中获取最终数据的查询操作

3. table - 关联的表名

表示当前行的执行计划对应的数据表,取值为表名、表别名(如示例中的u1u2),若为衍生表则会显示derived+数字(数字对应id)。

4. type - 表访问类型【核心】

type表示MySQL访问表中数据的方式,直接反映查询是否使用索引、使用的索引效率如何,是判断SQL性能的核心指标
type的性能从优到劣依次排序为:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL

实际优化中,重点关注前7个常用等级,目标是至少优化到range级别,最好达到refeq_ref级别,常见核心取值及含义:

  • system:特殊的const类型,表中只有一行数据(如系统表),性能最优
  • const:通过主键/唯一索引一次匹配到唯一行数据,MySQL会将其转换为常量处理,查询极快
  • eq_ref:多表连接时,通过主键/唯一索引关联,被连接表的每一行都只匹配一行结果,性能仅次于const
  • ref:通过非唯一索引进行数据查询,匹配到多行符合条件的数据,是单表查询中较优的级别
  • range:使用索引进行范围查询(如><INBETWEEN等),仅扫描索引范围内的数据
  • index:扫描整个索引树获取数据,未回表但扫描了全部索引,性能远差于range
  • ALL全表扫描,未使用任何索引,扫描表中所有数据,性能最差,需坚决优化

5. possible_keys - 可命中的索引集合

表示当前查询理论上可以使用的所有索引,MySQL优化器会从该集合中筛选出最优索引作为实际执行的索引。
该字段仅为候选索引参考,不代表实际使用,若字段值为NULL,表示查询无可用索引。

6. key - 实际使用的索引【核心】

表示MySQL优化器最终选中执行查询的索引,是判断查询是否真正走索引的关键依据。

  • 若字段值为NULL,表示查询未使用任何索引(大概率是全表扫描ALL
  • 若需强制MySQL使用/忽略候选索引,可使用FORCE INDEXUSE INDEXIGNORE INDEX关键字指定

7. key_len - 索引使用的字节长度

表示查询中实际使用的索引字段字节数,可通过该字段判断索引的使用程度(是否使用了复合索引的所有列)。
核心特点:

  • key_len根据表定义计算的理论最大长度,非实际数据的使用长度
  • 优化原则:在不损失查询精度的前提下,key_len越短越好,索引使用效率更高

8. ref - 索引关联的列/常量

表示查询中用于匹配索引的列名或常量,反映索引与其他数据的关联方式,常见取值:

  • const:使用常量值匹配索引(如示例中的name='wyh'
  • 表名/列名:多表连接时,使用其他表的列值匹配索引(如示例中的ssb_test.u1.id
  • NULL:未使用索引关联,直接扫描

9. rows - 预估扫描行数

表示MySQL根据表统计信息和索引使用情况,预估需要扫描的行数,用于判断查询的大致数据量。
核心说明:

  • 该值为预估数值,非实际扫描的精确行数
  • 优化原则:行数越少越好,扫描行数越少,查询效率越高

10. filtered - 结果过滤比例

表示通过WHERE条件过滤后,符合查询条件的记录占扫描行数的比例,取值范围0-100(百分比)。

  • 数值越接近100,说明过滤效果越好,无用数据扫描越少
  • 数值越低,说明大部分扫描的行都不符合条件,查询的过滤条件设计不合理

11. Extra - 额外执行信息【核心】

Extra包含了不适合在其他列展示,但对性能至关重要的额外执行信息,是定位隐性性能问题的关键,常见核心取值及含义:

  • Using filesort:MySQL无法利用索引完成排序,需进行外部文件排序,性能损耗大,必须优化
  • Using temporary:查询过程中创建了临时表,常见于ORDER BYGROUP BY,性能损耗大,需优化
  • Not exists:MySQL对LEFT JOIN的优化策略,找到匹配行后立即停止扫描,属于优化项
  • Using index:使用了覆盖索引,直接从索引中获取所有查询数据,无需回表,性能最优
  • Using index condition:MySQL5.6新增的索引条件推送特性,可在二级索引上执行部分过滤条件,减少回表IO,属于优化项
  • Using where:MySQL将存储引擎返回的数据在服务层进行WHERE条件过滤,说明存储引擎未完成全部过滤
  • Using join buffer:多表连接时使用了连接缓存,说明连接条件未使用索引,需优化
  • Impossible whereWHERE子句的条件永远为false,无法查询到任何数据(如非空列执行is null
  • NULL:无特殊额外信息,查询执行流程正常

三、EXPLAIN优化核心原则

  1. 优先保证type字段至少达到range级别,杜绝indexALL(全表扫描/全索引扫描)
  2. 确保key字段非NULL,查询必须走有效索引,避免索引失效
  3. 坚决杜绝Extra字段出现**Using filesortUsing temporary**,这两个是性能优化的重灾区
  4. 尽可能让rows预估扫描行数最小化,减少数据扫描量
  5. 利用Using index覆盖索引优化,避免回表查询,大幅提升查询效率
  6. possible_keys有值但key为NULL,说明索引失效,需排查索引使用条件(如字段类型不匹配、使用函数等)
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐