慢查询是性能问题的「第一现场」。 本文从「我看到慢」到「我修好了」完整走一遍。

第一步:抓现场

-- 1. 实时正在执行的慢 SQL
SHOW FULL PROCESSLIST;

-- 2. 慢日志开关与位置
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';

-- 3. 找到当前最慢的几条
SELECT * FROM information_schema.PROCESSLIST
WHERE COMMAND != 'Sleep' ORDER BY TIME DESC LIMIT 10;

第二步:看执行计划

EXPLAIN SELECT id, title FROM posts WHERE status=1 AND created_at > '2026-01-01' ORDER BY views DESC LIMIT 20;

重点看:

  • type:ALL(全表扫)→ ref/range → const(最优)
  • rows:扫描行数,越少越好
  • Extra:Using filesort / Using temporary 是常见性能杀手

第三步:定位原因

常见模式:

  1. 索引缺失:WHERE 字段没有索引 → 加索引
  2. 索引失效:函数包裹(YEAR(created_at))、类型转换('1' = 1)、最左前缀未命中
  3. 回表过多:需要 SELECT * 但只用 1 个字段 → 覆盖索引
  4. 排序代价高:ORDER BY 字段无索引 → 加联合索引
  5. 分页过深:LIMIT 1000000, 20 → 游标分页(WHERE id > ? LIMIT 20)
  6. JOIN 笛卡尔积:ON 条件缺失 / 关联字段类型不一致

第四步:优化 + 验证

-- 优化前后对比
SET profiling = 1;
SELECT ...;
SHOW PROFILES;
SHOW PROFILE FOR QUERY 1;

另外用 SHOW STATUS LIKE 'Handler_read%' 看「索引命中次数」:

  • Handler_read_key 高 = 索引使用充分
  • Handler_read_rnd 高 = 临时表 / 文件排序多

第五步:建立防御机制

  • 慢日志:开启、设置 long_query_time = 1、定期分析
  • 监控:每分钟慢查询数、Top 10 慢 SQL 推送告警
  • SQL Review:大表加字段、改 WHERE 条件需要 review
  • 压测:上线前用真实数据量跑回归

需要专业排查?查看性能优化服务 或 提交体检。