mysql数据库的查询优化器与执行计划分析

来源:这里教程网 时间:2026-02-28 20:53:10 作者:

怎么看 MySQL 的执行计划(EXPLAIN)

直接在

SELECT
语句前加
EXPLAIN
,就能看到优化器打算怎么执行这条查询。它不真正运行查询,只返回执行计划的元信息。

关键字段要盯紧:

type
(访问类型)、
key
(实际用的索引)、
rows
(预估扫描行数)、
Extra
(额外操作,比如
Using filesort
Using temporary
)。

示例:

EXPLAIN SELECT * FROM orders WHERE user_id = 123 AND status = 'paid';
type
ref
range
好,
range
又比
ALL
(全表扫描)好
key
为空说明没走索引,得查原因:是不是索引失效?字段类型隐式转换?函数包裹了索引列?
rows
如果远大于实际结果集,往往意味着索引选择不当或统计信息过期,可运行
ANALYZE TABLE orders;

为什么
ORDER BY
有时不走索引

MySQL 只有在满足“索引最左前缀 + 排序方向一致 + 无范围条件中断”的前提下,才能利用索引完成排序。一旦破坏任一条件,就会触发

Using filesort

常见断点场景:

WHERE
中用了范围查询(如
created_at > '2024-01-01'
),后面跟的
ORDER BY id
就无法复用联合索引中的
id
ORDER BY a ASC, b DESC
—— 多数版本不支持混合排序方向走索引(8.0.12+ 开始部分支持,但需显式定义降序索引)
SELECT *
+
ORDER BY indexed_col
,但
WHERE
条件没覆盖该索引的最左列

验证方式:看

EXPLAIN
输出中
Extra
是否含
Using filesort
;若存在,优先考虑调整索引顺序或拆分查询逻辑。

联合索引怎么建才不被“浪费”

联合索引不是字段简单堆砌,顺序决定它能覆盖哪些查询模式。优化器只会按索引定义的从左到右顺序匹配

WHERE
条件和
ORDER BY

建索引前先问三个问题:

哪些字段最常出现在
WHERE
等值条件中?放最左
是否有范围查询(
>
,
BETWEEN
,
LIKE 'abc%'
)?它右边的字段就无法用于索引查找
是否需要避免
filesort
?把
ORDER BY
字段尽可能放在范围条件之后、索引末尾

例如,高频查询是:

WHERE category = ? AND status IN (?, ?) ORDER BY created_at DESC
,那么
(category, status, created_at)
是合理顺序;而
(status, category, created_at)
就会导致
category = ?
无法使用索引前缀。

查询优化器“选错索引”怎么办

优化器依赖表统计信息做成本估算,但数据分布倾斜、长期未更新统计、或复杂表达式都可能导致它误判。典型表现是明明有索引却走了全表扫描,或选了低效的索引。

可干预手段有限但实用:

强制指定索引:
SELECT * FROM t USE INDEX (idx_user_status) WHERE ...
(慎用,后续数据增长可能让该索引再次变差)
更新统计信息:
ANALYZE TABLE t;
,尤其在大批量导入/删除后
检查是否因隐式类型转换导致索引失效:比如
user_id
INT
,但传入字符串
'123'
,会触发全字段转类型,索引失效
SHOW WARNINGS
查看优化器重写后的语句,有时能发现意外的子查询展开或条件合并

真正棘手的是优化器在多个“看起来差不多”的索引间摇摆——这时候往往不是调优问题,而是数据模型或查询结构本身需要收敛,比如把大表关联拆成应用层分步查,或引入冗余排序字段减少动态计算。

相关推荐