怎么看 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查看优化器重写后的语句,有时能发现意外的子查询展开或条件合并
真正棘手的是优化器在多个“看起来差不多”的索引间摇摆——这时候往往不是调优问题,而是数据模型或查询结构本身需要收敛,比如把大表关联拆成应用层分步查,或引入冗余排序字段减少动态计算。
