萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 程式設計 >  >> 資料庫 >> MySQL 教學

MySQL EXPLAIN 执行计划深度解析:id、select_type、type、key、rows、Extra 逐列详解与实战案例

基础语法

EXPLAIN SELECT ...          -- 分析查询执行计划
EXPLAIN EXTENDED SELECT ... -- 显示额外优化器信息(5.7+ 默认开启)
EXPLAIN tbl_name            -- 等同 DESC tbl_name / SHOW COLUMNS FROM tbl_name

输出列详解

列名含义关键值解读
idSELECT 标识符,编号递增表示执行顺序相同 id 从上到下执行;id 越大越先执行(子查询)
select_type查询类型见下表
table访问的表/衍生表<derivedN> 表示派生表(子查询结果集)
partitions匹配的分区(分区表)—
type访问类型(核心性能指标)system > const > eq_ref > ref > range > index > ALL
possible_keys可能用到的索引NULL 表示无可用索引
key实际使用的索引NULL 表示全表扫描
key_len索引长度(字节)推断联合索引用了几列
ref与索引比较的列/常量const、func、列名
rows预估扫描行数越小越好,统计信息不准时偏差大
filtered按条件过滤后剩余行百分比100 表示无过滤
Extra额外信息见下表

select_type 取值

值含义
SIMPLE简单查询(无子查询/UNION)
PRIMARY最外层查询
UNIONUNION 中第二个及后续 SELECT
DEPENDENT UNION依赖外部查询的 UNION
UNION RESULTUNION 合并结果
SUBQUERY子查询中第一个 SELECT
DEPENDENT SUBQUERY依赖外部查询的子查询
DERIVEDFROM 子句中的派生表
UNCACHEABLE SUBQUERY/UNION结果不可缓存,每行重新评估

type 访问类型(由优到劣)

  • system:表仅一行(const 特例)。
  • const:主键/唯一索引等值查询,最多一行,极快。
  • eq_ref:唯一索引/主键等值连接,每行匹配一行。
  • ref:非唯一索引等值连接/查询,匹配多行。
  • ref_or_null:ref + 额外搜索 NULL。
  • index_merge:索引合并优化(Using union/intersect/sort_union)。
  • unique_subquery:IN 子查询主键优化。
  • index_subquery:IN 子查询非唯一索引优化。
  • range:索引范围扫描(BETWEEN、IN、>、< 等)。
  • index:全索引扫描(覆盖索引时常见)。
  • ALL:全表扫描(最差)。

Extra 关键信息

值含义优化方向
Using index覆盖索引(仅读索引)✅ 优秀
Using whereServer 层过滤⚠️ 结合索引下推
Using temporary需创建临时表(GROUP BY/ORDER BY 无索引)❌ 优化索引/避免临时表
Using filesort需文件排序(ORDER BY 无索引)❌ 增加排序索引
Using join buffer连接使用 Join Buffer(无索引)❌ 加连接索引
Impossible WHEREWHERE 恒假✅ 无需执行
Select tables optimized away聚合函数直接用索引✅ 极快

实战案例演示

案例 1:主键等值查询(const)

EXPLAIN SELECT * FROM books WHERE book_id = 1;
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | books | const | PRIMARY       | PRIMARY | 4       | const |    1 |       |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+

案例 2:嵌套子查询执行顺序

EXPLAIN SELECT * FROM (SELECT * FROM (SELECT * FROM t3 WHERE id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table      | type   | possible_keys     | key     | key_len | ref  | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
|  1 | PRIMARY     |  | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  2 | DERIVED     |  | system | NULL              | NULL    | NULL    | NULL |    1 |       |
|  3 | DERIVED     | t3         | const  | PRIMARY,idx_t3_id | PRIMARY | 4       |      |    1 |       |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+

执行顺序:id=3 → id=2 → id=1(从内向外)。

案例 3:UNION 与 DEPENDENT SUBQUERY

EXPLAIN SELECT * FROM t3 WHERE id IN (SELECT id FROM t3 WHERE id=3952602 UNION ALL SELECT id FROM t3);
+----+--------------------+-------+--------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type        | table | type   | possible_keys     | key     | key_len | ref   | rows | Extra                    |
+----+--------------------+-------+--------+-------------------+---------+---------+-------+------+--------------------------+
|  1 | PRIMARY            | t3    | ALL    | NULL              | NULL    | NULL    | NULL  | 1000 | Using where              |
|  2 | DEPENDENT SUBQUERY | t3    | const  | PRIMARY,idx_t3_id | PRIMARY | 4       | const |    1 | Using index              |
|  3 | DEPENDENT UNION    | t3    | eq_ref | PRIMARY,idx_t3_id | PRIMARY | 4       | func  |    1 | Using where; Using index |
|NULL| UNION RESULT       |  | ALL | NULL              | NULL    | NULL    | NULL  | NULL |                          |
+----+--------------------+-------+--------+-------------------+---------+---------+-------+------+--------------------------+

外层 PRIMARY 走全表扫描(ALL),子查询部分走索引。

优化清单

  1. type=ALL → 检查 WHERE/JOIN 列是否有索引,考虑添加复合索引。
  2. Using filesort / Using temporary → 增加 ORDER BY/GROUP BY 对应索引,或调整 SQL 逻辑。
  3. key=NULL 但 possible_keys 有值 → 索引选择性太低,优化器放弃,考虑 FORCE INDEX 或重写查询。
  4. rows 极大 → 分区表、分库分表、增加过滤条件。
  5. 定期 ANALYZE TABLE 更新统计信息,保证优化器决策准确。
copyright © 萬盛學電腦網 all rights reserved