慢查询调优核心是诊断驱动的精准优化:先通过explain看type(目标ref/range,避免all)、key(是否实际使用索引)和rows(扫描行数是否合理),再结合索引失效场景(函数操作、%开头like、最左前缀不满足、隐式转换)及设计原则(高区分度字段前置、覆盖索引、删除冗余索引)进行针对性优化。

慢查询调优的核心是“先看怎么执行,再决定怎么建索引”。直接加索引容易失效或无效,必须结合 EXPLAIN 执行计划 看清 MySQL 实际做了什么——它是否用了索引、扫了多少行、有没有排序或临时表。整个过程不是试错,而是诊断驱动的精准优化。
看懂 EXPLAIN 的三个关键字段
执行 EXPLAIN SELECT ... 后,重点关注以下三项:
-
type:访问类型。优先目标是
ref或range;出现ALL就是全表扫描,必须干预;const或eq_ref是最优状态。 -
key:实际生效的索引名。如果为
NULL,说明没走索引(哪怕possible_keys有值)。 - rows:预估扫描行数。这个数字越接近实际返回行数越好;若远大于结果集(比如查 10 条却扫 10 万行),说明索引没发挥效力或条件选择性差。
索引是否真正生效?盯住这些典型失效场景
很多索引“建了等于没建”,常见原因包括:
- 在 WHERE 条件中对索引列做函数操作,如
WHERE YEAR(create_time) = 2024→ 改成WHERE create_time BETWEEN '2024-01-01' AND '2024-12-31'。 - LIKE 模糊匹配以
%开头,如WHERE name LIKE '%abc'→ 无法使用索引;LIKE 'abc%'可用。 - 联合索引未满足最左前缀,如索引是
(a, b, c),但查询只用WHERE b = 1→ 不命中;必须包含a才能触发。 - 隐式类型转换,如字段是
VARCHAR却传入数字:WHERE mobile = 13800138000→ MySQL 自动转类型,索引失效;应写成WHERE mobile = '13800138000'。
高效索引设计的实用原则
索引不是越多越好,要按查询模式精准构建:
- 高频过滤字段优先放前面(尤其高区分度的,如
user_id比status更适合作联合索引首列)。 - 把 ORDER BY 和 GROUP BY 字段纳入联合索引尾部,避免
Using filesort;例如查WHERE user_id = ? ORDER BY create_time DESC,建INDEX idx_user_time (user_id, create_time)。 - 追求覆盖索引:让索引包含 SELECT 中所有字段,直接从索引取数,不回表。如
SELECT name, email FROM users WHERE status = 'active',可建INDEX idx_status_ne (status, name, email)。 - 删除冗余索引:已有
(a, b)就不必单独建(a);可用sys.schema_unused_indexes视图辅助识别。
分页、JOIN、子查询的针对性优化
这些结构容易放大索引失效影响,需特别处理:
- 深分页(
LIMIT 100000, 20):避免跳过大量数据,改用游标方式,如WHERE id > last_seen_id ORDER BY id LIMIT 20。 - JOIN 表顺序:小结果集表作驱动表;确保被驱动表的关联字段有索引(如
orders.user_id应有索引)。 - IN 子查询性能差时,优先改写为 JOIN;若子查询结果固定且不大,也可考虑用临时表缓存结果再关联。











