【MySQL】EXPLAIN 关键字详解

​EXPLAIN 是用于分析 SQL 查询的执行计划。它能揭示 MySQL 如何执行查询(如是否使用索引、表连接顺序等),帮助我们定位性能瓶颈。
基本用法

EXPLAIN SELECT * FROM users WHERE age > 25;

输出列

列名 说明 关键值示例
id 查询标识符(相同 id 表示同组查询,执行顺序从上到下;不同 id 值越大优先级越高) 1(主查询)、2(子查询)
select_type 查询类型 SIMPLE(无子查询)、PRIMARY(外层查询)、SUBQUERY(子查询)
table 访问的表名 users<derived2>(派生表)、<union1,2>(UNION 结果)
partitions 匹配的分区 p0,p1(分区表使用)
type 访问类型(性能核心指标,从优到劣排序) 重点顺序:system > const > eq_ref > ref > range > index > ALL
possible_keys 可能使用的索引 idx_age(显示可选的索引名)
key 实际使用的索引 idx_email(若为 NULL 表示未用索引)
key_len 索引使用的字节数 4(int 索引)、152(varchar(50))
ref 索引匹配的列或常量 const(常量)、db1.users.id(其他表的列)
rows 预估扫描行数(越小越好) 10(理想)、10000(需优化)
filtered 存储引擎返回数据后在 server 层过滤的比例 100.0(完全匹配)、10.0(仅 10% 数据有效)
Extra 额外执行信息(重要优化线索) Using indexUsing temporaryUsing filesort(需警惕)
  1. id - 查询标识符

    • 说明

      ① 标识 SELECT 所属的查询块

      ② 相同 id 表示同一查询级别,执行顺序从上到下

      ③ 不同 id 时,值越大优先级越高(越先执行)

    • 典型值

      ① 单查询:1

      ② 嵌套查询:1(主查询),2(子查询)

      ③ UNION:NULL(UNION 结果集)

  2. select_type - 查询类型

    描述 示例场景
    SIMPLE 简单 SELECT(无子查询/UNION) SELECT * FROM users
    PRIMARY 最外层查询 包含子查询时的外层查询
    SUBQUERY SELECT 中的子查询 SELECT id, (SELECT name FROM profiles) FROM users
    DERIVED FROM 子句中的子查询 SELECT * FROM (SELECT * FROM orders) tmp
    UNION UNION 中的第二个或后续 SELECT SELECT a FROM t1 UNION SELECT b FROM t2
    UNION RESULT UNION 结果 UNION 操作的结果集
    DEPENDENT SUBQUERY 依赖外部查询的子查询 子查询依赖外层查询结果
    MATERIALIZED 物化子查询(MySQL 5.6+) 子查询结果被物化为临时表
  3. table - 访问的表

    • 说明:

      ① 显示表名或别名

      ② 特殊格式:

    (1) <derivedN>:id=N 的派生表

    (2) <unionM,N>:id=M 和 N UNION 的结果

    (3) <subqueryN>:物化子查询

  4. partitions - 匹配的分区

    • 说明:
      ① 对于分区表,显示查询访问的分区
      ② 非分区表始终为 NULL

    • 示例:p0,p1(访问分区 p0 和 p1)

  5. type ⭐(关键性能指标)- 访问类型
    说明: 按性能从优到劣排序

    类型 描述 性能 示例
    system 系统表,仅一行 最优 MyISAM 引擎的空表
    const 主键/唯一索引的常量查询 极优 WHERE id = 1
    eq_ref JOIN 时主键/唯一索引关联 JOIN ... ON t1.pk = t2.pk
    ref 非唯一索引的等值查询 WHERE index_col = 10
    fulltext 全文索引 MATCH(...) AGAINST(...)
    ref_or_null ref + NULL 值搜索 WHERE col = 10 OR col IS NULL
    index_merge 索引合并优化 多个索引条件组合
    unique_subquery 唯一索引子查询 value IN (SELECT pk FROM ...)
    index_subquery 非唯一索引子查询 中下 value IN (SELECT index_col FROM ...)
    range 索引范围扫描 中下 WHERE id > 10
    index 全索引扫描 SELECT indexed_col FROM table
    ALL 全表扫描 最差 无索引查询
  6. possible_keys - 可能使用的索引

    • 说明:

      ① 查询可能选择的索引列表

      ② NULL 表示无可用索引

      ③ 实际使用的索引可能在 key 列不同

  7. key ⭐ - 实际使用的索引

    • 说明:

      ① 查询优化器最终选择的索引

      ② NULL 表示未使用索引

      ③ 可能不在 possible_keys 中(优化器选择更优索引)

  8. key_len - 使用索引的长度(字节)

    • 计算规则:

      ① 数值类型:

            (1) TINYINT:1 字节
      
            (2) INT:4 字节
      
            (3) BIGINT:8 字节
      

      ② 字符串类型(UTF8mb4):

            (1) CHAR(10):4×10 = 40 字节
      
            (2) VARCHAR(10):4×10 + 长度字节(2字节)
      

      ③ NULL 标志:1 字节(若列可为 NULL)

    • 示例:

      int NOT NULL:4

      varchar(255) NULL:255×4 + 2 + 1 = 1023

  9. ref - 索引比较的列或常量

    • 格式:
      const:常量值
      func:函数结果
      db.table.column:关联表的列

    • 示例:

      WHERE col = 10const
      JOIN ... ON t1.id = t2.user_id → db.t2.user_id

  10. rows ⭐ - 预估扫描行数

  • 说明:
    ① 存储引擎层面预估的检查行数
    ② 重要性能指标(值越小越好)
    ③ 非精确值,基于统计信息估算
  1. filtered - 存储引擎返回数据的过滤百分比

    • 说明:
      ① MySQL 5.7+ 新增列
      ② 表示条件过滤后剩余数据的百分比
      ③ 计算最终行数:rows × filtered%

    • 示例:

      ① rows=1000, filtered=10.00 → 最终约 100 行

  2. Extra ⭐(重要优化线索)- 附加执行信息
    关键值详解:

    含义 优化建议
    Using index 覆盖索引(无需回表) 优,保持
    Using where Server 层过滤数据 检查索引使用
    Using temporary 使用临时表 优化 GROUP BY/ORDER BY
    Using filesort 额外排序操作 为排序字段加索引
    Select tables optimized away 使用聚合函数优化
    Using index condition 索引条件下推(ICP) MySQL 5.6+ 优化特性
    Using join buffer 使用连接缓冲区 增大 join_buffer_size
    Impossible WHERE WHERE 条件永不成立 查询逻辑错误
    Distinct 优化 DISTINCT 操作 -

优化简单总结:

  • 优先优化 type 列: 避免 ALL 和 index;
  • 检查索引使用: key 不为 NULL,且 key_len 合理;
  • 关注扫描行数: rows 值应尽可能小;
  • 警惕额外操作: Using filesort 和 Using temporary 需优化;
  • 善用覆盖索引: Using index 是最佳状态之一。

你可能发现你使用 EXPLAIN 后,输出的列只有 10 列或者 11 列,那是因为MySQL版本的缘故。小于 5.7 的版本,只会有 10 列输出。版本越高,优化升级会越多,能让我们更准确地判断索引选择和过滤效率。

Logo

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

更多推荐