返回首页

MySQL 慢查询排查案例复盘 — 从发现到根治的完整链路

📅 创建于 2026-05-12 🔄 更新于 2026-05-12 📝 353 字

MySQL 慢查询排查案例复盘

真实线上案例:系统卡顿 → 慢查询定位 → EXPLAIN 分析 → 索引优化 → 性能对比验证

问题背景

晚上 8 点接到告警,线上系统响应变慢,页面平均加载时间从 200ms 飙升到 5s+。监控显示数据库 CPU 从 20% 飙升到 85%。

第一步:定位慢查询

-- 开启慢查询日志(如果还没开)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;

-- 查看当前正在执行的慢查询
SELECT * FROM information_schema.PROCESSLIST
WHERE COMMAND != 'Sleep' AND TIME > 2
ORDER BY TIME DESC;

当场抓到一条耗时 4.7s 的查询:

SELECT o.order_id, o.total_amount, o.status, u.username, u.phone
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
WHERE o.created_at > '2025-01-01'
ORDER BY o.total_amount DESC
LIMIT 20;

第二步:EXPLAIN 分析

EXPLAIN SELECT o.order_id, o.total_amount, o.status,
    u.username, u.phone
FROM orders o
LEFT JOIN users u ON o.user_id = u.id
WHERE o.created_at > '2025-01-01'
ORDER BY o.total_amount DESC
LIMIT 20;

结果分析:

字段 结论
o.type ALL orders 全表扫描
o.rows 980000 扫描了 98 万行
o.Extra Using where; Using filesort 文件排序(未用索引排序)
u.type eq_ref users 表索引正常
u.rows 1 每次关联扫描 1 行

问题确认:

  1. orders 表全表扫描 — created_at 没有索引
  2. Using filesorttotal_amount 也没有索引,排序在磁盘上完成
  3. 两张问题叠加:全表扫描 + 文件排序 = 灾难

第三步:加索引

-- 创建复合索引(覆盖 WHERE 条件和 ORDER BY)
ALTER TABLE orders ADD INDEX idx_create_amount (created_at, total_amount);

设计思路:

  • created_at 放前面:满足 WHERE 范围查询
  • total_amount 放后面:满足 ORDER BY 排序,且因 created_at 过滤后有排序稳定性

第四步:效果验证

优化前(4.7s → 优化后 23ms):

# 优化前
# Query_time: 4.718782  Lock_time: 0.000162  Rows_sent: 20  Rows_examined: 980000

# 优化后
# Query_time: 0.023401  Lock_time: 0.000108  Rows_sent: 20  Rows_examined: 56218
指标 优化前 优化后 提升倍数
查询耗时 4.72s 23ms 205x
扫描行数 980,000 56,218 17x
数据库 CPU 85% 30% 恢复正常

复盘要点

  1. 索引缺失是慢查询最常见的根因created_at 没有索引导致全表扫描
  2. 复合索引设计 — WHERE + ORDER BY 的列可以放在同一个索引中,避免 filesort
  3. EXPLAIN 必须成为排查习惯type=ALL + Extra=Using filesort 是两个最危险的红旗信号
  4. 分步验证 — 加索引前记录 baseline,加索引后对比执行计划,确认走索引

关联页面

页面 关联点
mysql-performance-config MySQL 性能调优总纲(慢查询/索引失效/深度分页/锁分析/配置模板)
mysql-replication-guide MySQL 主从复制,慢查询对从库延迟的影响
fullstack-performance-troubleshooting 全栈排障方法论(Nginx→应用→数据库→服务器)