MySQL执行计划是什么?从原理到实战的完整解析
本文系统介绍了MySQL执行计划的原理与优化实践。执行计划通过EXPLAIN命令获取,展示查询优化器生成的执行路径,包含表连接顺序、访问方式等关键信息。重点解析了type字段(连接类型,从最优const到最差ALL)、Extra字段(额外提示)等核心指标,并通过典型案例说明如何优化索引失效、减少扫描行数等。文章提出执行计划优化三原则:优先索引扫描、避免临时表和消除文件排序,同时给出了复合索引设计、
·
引言
在MySQL性能优化中,执行计划(Execution Plan)是开发者手中的"X光机"。本文将通过原理剖析、字段解析和实战案例,系统解读这个DBA必备的调优工具。
一、执行计划的核心定义
MySQL执行计划是查询优化器根据统计信息生成的查询执行路径图,通过EXPLAIN
命令输出,展示以下关键信息:
- 数据访问方式(全表扫描/索引扫描)
- 表连接顺序与类型
- 临时表使用情况
- 排序操作实现方式
二、如何获取执行计划
2.1 基础命令
EXPLAIN SELECT * FROM users WHERE age > 18;
2.2 增强版(MySQL 8.0+)
EXPLAIN ANALYZE SELECT * FROM users WHERE age > 18;
-- 实际执行并显示耗时
三、执行计划关键字段详解
3.1 核心字段矩阵
字段 | 含义 | 示例值 |
---|---|---|
id | 查询块编号(子查询/UNION时递增) | 1 |
select_type | 查询类型(SIMPLE/PRIMARY/SUBQUERY/UNION等) | SIMPLE |
table | 当前操作的表名(可能显示衍生表或临时表) | users |
partitions | 命中的分区(分表场景) | p0,p1 |
type | 连接类型(决定性能的关键指标) | ref |
possible_keys | 可能用到的索引 | idx_age |
key | 实际使用的索引 | idx_age |
key_len | 索引使用长度(判断复合索引使用情况) | 4 |
ref | 与索引比较的列或常量 | const |
rows | 预估扫描的行数(越小越好) | 100 |
filtered | 按条件过滤后的行百分比 | 10.0 |
Extra | 额外信息(重要提示区) | Using index condition |
3.2 关键字段深度解析
(1) type字段详解(从最优到最差)
- system:表只有一行(系统表)
- const:通过索引一次找到(主键/唯一索引)
- eq_ref:连接时使用主键/唯一索引
- ref:非唯一索引查找
- range:范围扫描(BETWEEN/IN/>)
- index:全索引扫描(覆盖索引)
- ALL:全表扫描(最差)
示例:
EXPLAIN SELECT * FROM users WHERE id = 100;
-- type=const(最佳)
EXPLAIN SELECT * FROM users WHERE age > 18;
-- type=range(可接受)
EXPLAIN SELECT * FROM users;
-- type=ALL(需优化)
(2) Extra字段重要提示
- Using index:覆盖索引(最佳)
- Using where:需要回表查询(可能存在索引失效)
- Using temporary:使用临时表(需警惕)
- Using filesort:文件排序(性能瓶颈)
- Impossible WHERE:条件矛盾(如age=18 AND age=20)
四、执行计划实战分析
4.1 典型优化案例
原始查询(未优化):
EXPLAIN SELECT * FROM orders
JOIN users ON orders.user_id = users.id
WHERE users.age > 18 AND orders.status = 'completed'
执行计划分析:
id | select_type | table | type | possible_keys | key | rows | Extra
---|-------------|-------|-------|------------------------|-------------|------|------------------
1 | SIMPLE | users | range | idx_age,idx_user_pk | idx_age | 5000 | Using where
1 | SIMPLE | orders| ref | idx_status,idx_user_id | idx_user_id | 10 | Using index
优化建议:
- 为orders表增加复合索引
idx_status_user_id(status,user_id)
- 调整查询顺序,优先过滤status字段
- 使用覆盖索引避免回表
4.2 索引失效典型场景
问题查询:
EXPLAIN SELECT * FROM users
WHERE DATE(create_time) = '2025-09-01'
执行计划:
type=ALL, Extra=Using where
原因:对索引列使用函数导致失效
优化方案:
-- 改写为范围查询
SELECT * FROM users
WHERE create_time >= '2025-09-01 00:00:00'
AND create_time < '2025-09-02 00:00:00'
五、执行计划优化原则
5.1 黄金三法则
- 减少扫描行数:优先使用索引扫描(type=ref/range)
- 避免临时表:警惕Extra中的Using temporary
- 消除文件排序:优化ORDER BY子句
5.2 索引优化策略
- 复合索引顺序:将过滤条件列放在联合索引左侧
- 覆盖索引:SELECT字段包含在索引中
- 索引下推:启用索引条件下推(ICP)
更多推荐
所有评论(0)