Mysql查看执行计划、explain关键字详解(超详细)

一、什么是explain

EXPLAIN 是 MySQL 提供的用于分析 SQL 查询执行计划的工具,通过该命令可以获取查询优化器选择的执行路径。

总结: explain可以查看sql执行时是否有使用到索引,关联查询时可以查看sql的执行顺序。

Explain被称为执行计划,在语句之前增加 explain 关键字,MySQL 会在查询上设置一个标记,模拟MySQL优化器来执行SQL语句,执行查询时,会返回执行计划的信息,并不执行这条SQL。(注意,如果 from 中包含子查询,仍会执行该子查询,将结果放入临时表中)。

在 MySQL 8.0 版本后,新增 EXPLAIN ANALYZE 功能,可提供实际执行统计信息。

二、explain基础用法

1. 基本语法

ini 复制代码
EXPLAIN [FORMAT = {TRADITIONAL|JSON|TREE}] SELECT ...;

AI写代码sql
1

解释:explain+sql语句,执行后就可以查看该sql的执行顺序,是否使用索引等信息。

2. 常用参数

  • FORMAT:指定输出格式(默认传统表格)
  • PARTITIONS:显示分区信息
  • ANALYZE:实际执行并收集统计(8.0+)

3. 输出示例

sql 复制代码
EXPLAIN SELECT * FROM employees WHERE last_name = 'tom';

AI写代码sql
1

输出结果示例:

sql 复制代码
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | employees | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 3000 |    10.00 | Using where |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+-------------+

AI写代码sql
12345

典型输出包含以下核心列:

列名 说明 关键值
id 查询序列号 相同id按顺序执行,不同id从大到小执行
select_type 查询类型 SIMPLE/PRIMARY/SUBQUERY/DERIVED/UNION
table 访问的表名 <unionM,N> 表示联合查询结果
partitions 匹配的分区 分区表可见具体分区
type 访问类型 system > const > eq_ref > ref > range > index > ALL
possible_keys 可能使用的索引 显示候选索引列表
key 实际使用的索引 NULL 表示未使用索引
key_len 索引长度 复合索引实际使用部分长度
ref 索引比较的列 const/库名.表名.列名
rows 预估扫描行数 基于统计信息估算
filtered 过滤百分比 100% 表示完全匹配索引
Extra 附加信息 Using filesort/Using temporary/Using index

三、执行计划字段深度解析

3.1、id 列

  • 查询执行顺序标识
  • 相同 id 表示同级别执行
  • 数字越大优先级越高
  • NULL 表示结果集合并

3.2、select_type 类型

类型 描述
SIMPLE 简单查询(无子查询或UNION)
PRIMARY 外层查询
SUBQUERY 子查询中的第一个SELECT
DERIVED 派生表(FROM子句中的子查询)
UNION UNION中的第二个或之后的SELECT
UNION RESULT UNION的结果

3.3、type 访问类型(性能关键指标)

按性能从优到劣排序:
system > const > eq_ref > ref > range > index > ALL

类型 扫描方式 出现场景
system 系统表单行记录 MyISAM引擎统计表
const 主键/唯一索引等值查询 WHERE id = 1
eq_ref 唯一索引关联查询 JOIN使用主键或唯一索引
ref 非唯一索引查找 普通二级索引查询
range 索引范围扫描 BETWEEN、IN、> 等范围查询
index 全索引扫描 覆盖索引但需扫描全部索引
ALL 全表扫描 无可用索引或需要读取大部分数据

1. type 访问类型详解(性能从优到劣)

  • system:系统表单行访问(内存表)
  • const:主键或唯一索引等值查询
sql 复制代码
   EXPLAIN SELECT * FROM users WHERE id = 1;

AI写代码sql
1
  • eq_ref:关联查询主键匹配
sql 复制代码
   EXPLAIN SELECT * FROM orders 
   JOIN users ON orders.user_id = users.id;

AI写代码sql
12
  • ref:非唯一索引等值查询
sql 复制代码
   CREATE INDEX idx_age ON users(age);
   EXPLAIN SELECT * FROM users WHERE age = 30;

AI写代码sql
12
  • range:索引范围扫描
sql 复制代码
   EXPLAIN SELECT * FROM users WHERE age BETWEEN 20 AND 30;

AI写代码sql
1
  • index:全索引扫描
scss 复制代码
   EXPLAIN SELECT COUNT(*) FROM users USE INDEX(idx_age);

AI写代码sql
1
  • ALL:全表扫描(需重点优化)

3.4、key_len 计算规则

索引使用长度的计算方法:

scss 复制代码
key_len = 
  (字符列长度 * 字符集bytes) + 
  (是否NULL? 1:0) + 
  (变长类型? 2:0)

AI写代码sql
1234

示例:VARCHAR(255) utf8mb4 可为NULL列

ini 复制代码
(255*4) + 1 + 2 = 1023 bytes

AI写代码sql
1

3.5、Extra 重要信息

含义
Using index 覆盖索引扫描(无需回表)
Using where 存储引擎返回数据后在Server层过滤
Using temporary 使用临时表(常见于GROUP BY/ORDER BY)
Using filesort 额外排序操作(需优化索引或调整排序方式)
Using index condition 索引条件下推(ICP优化)
Select tables optimized away 通过索引直接获取统计信息(如MIN/MAX)

四、实战案例分析

案例1:索引失效分析

sql 复制代码
EXPLAIN SELECT * FROM orders WHERE YEAR(order_date) = 2023;

AI写代码sql
1

输出结果:

sql 复制代码
type: ALL
key: NULL
Extra: Using where

AI写代码sql
123

问题诊断:对列使用函数导致索引失效

优化方案:

sql 复制代码
ALTER TABLE orders ADD INDEX idx_order_date (order_date);
SELECT * FROM orders 
WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31';

AI写代码sql
123

案例2:连接查询优化

sql 复制代码
EXPLAIN 
SELECT e.name, d.department_name 
FROM employees e
JOIN departments d ON e.dept_id = d.id;

AI写代码sql
1234

输出显示:

sql 复制代码
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref          | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+
| 1  | SIMPLE      | e     | ALL    | dept_id       | NULL    | NULL    | NULL         | 1000 |             |
| 1  | SIMPLE      | d     | eq_ref | PRIMARY       | PRIMARY | 4       | company.e.dept_id | 1   | Using index |
+----+-------------+-------+--------+---------------+---------+---------+--------------+------+-------------+

AI写代码sql
123456

优化建议:为 employees 表的 dept_id 字段添加索引

五、高级技巧与最佳实践

5.1、JSON格式输出分析

ini 复制代码
EXPLAIN FORMAT=JSON SELECT ...;

AI写代码sql
1

可获取更详细的成本估算信息:

css 复制代码
{
  "query_block": {
    "cost_info": {
      "query_cost": "1.20"
    },
    "table": {
      "access_type": "range",
      "rows_examined_per_scan": 500,
      "rows_produced_per_join": 500,
      "filtered": "100.00",
      "cost_info": {
        "read_cost": "0.50",
        "eval_cost": "0.70",
        "prefix_cost": "1.20"
      }
    }
  }
}

AI写代码sql
123456789101112131415161718

5.2、执行计划可视化工具

推荐使用:

  • MySQL Workbench Visual Explain
  • Percona Toolkit 的 pt-visual-explain

5.3、优化器提示

强制使用指定索引:

sql 复制代码
SELECT * FROM table USE INDEX (index_name) ...

AI写代码sql
1

5.4、统计信息管理

sql 复制代码
ANALYZE TABLE table_name;  -- 更新统计信息
SHOW INDEX FROM table_name; -- 查看索引基数

AI写代码sql
12

六、常见误区与注意事项

  1. rows 列是估算值,实际值可能偏差较大
  2. 索引覆盖不代表高效,需结合扫描行数判断
  3. 并非所有 Using filesort 都需要优化,小数据量排序是正常现象
  4. 强制索引可能适得其反,需结合数据分布考虑
  5. 连接顺序不一定按书写顺序,优化器会自动选择最佳顺序

七、EXPLAIN 执行计划优化路线图

  1. 检查 type 列是否达到 range 级别以上
  2. 确认 possible_keys 和 key 是否合理
  3. 分析 key_len 是否充分利用索引
  4. 检查 rows 估算值是否过大
  5. 查看 Extra 列是否有警告信息
  6. 验证 filtered 百分比是否过低
  7. 对比优化前后的执行计划差异
相关推荐
IT爱学堂11 分钟前
Go开发疑难杂症终结者通关指南
后端
大勇前进22 分钟前
从10分钟到10秒:一个真实慢查询的SQL Server优化全记录
后端
站大爷IP23 分钟前
被Python异步坑了三年,才搞懂await和create_task的区别
后端
大白8023 分钟前
你的数据库密码还在用明文?SQL Server 凭据管理的 3 种现代方案
后端
凤山老林23 分钟前
Spring Boot 集成 ShardingSphere-Encrypt 实现字段级实时脱敏
java·spring boot·后端·数据脱敏
vipxieliang23 分钟前
ValidX v1.2.0 更新日志
java·后端
Zane199431 分钟前
只改一个方向的引用,循环引用就能立刻被回收?一文讲透 weakref 弱引用
后端·python
长大198831 分钟前
窗口函数用不好反而更慢?SQL Server中OVER子句的4个性能陷阱
后端
大黄评测31 分钟前
MERGE语句有Bug?SQL Server官方不推荐的背后真相与替代方案
后端
长大198833 分钟前
TempDB 爆满导致系统卡死?SQL Server TempDB 瓶颈诊断与根治方案
后端