07.2 - 慢查询排查方法论
定位:慢查询排查是 MySQL 生产环境最常用的技能——系统性的排查流程远比死记硬背技巧更重要 面试高频度:⭐⭐⭐⭐ 考查方式:慢查询排查的完整流程、怎么定位瓶颈、典型案例分析
一、排查流程总览
慢查询排查方法论
1. 发现慢查询
2. 获取执行计划
3. 分析瓶颈
4. 优化方案
5. 验证效果
┌──────────────────────────────────────────────────┐
│ Step 1: 发现 │
│ slow_query_log → SET long_query_time=1 │
│ SHOW PROCESSLIST → 看当前运行中的慢查询 │
│ 业务监控 → 用户反馈"页面上得慢" │
└──────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ Step 2: 获取执行计划 │
│ DESCRIBE / EXPLAIN [慢 SQL] │
│ EXPLAIN FORMAT=TREE [慢 SQL] (8.0+) │
│ SHOW WARNINGS → 查看优化器改写后的 SQL │
└──────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ Step 3: 分析瓶颈 │
│ │
│ ① 是不是全表扫描? (type=ALL) │
│ ② 有没有用索引? (key=NULL?) │
│ ③ 扫描行数多吗? (rows >> 实际结果) │
│ ④ 排序用临时表? (Extra: Using filesort) │
│ ⑤ 分组用临时表? (Extra: Using temporary) │
└──────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ Step 4: 优化方案 │
│ ① 添加或优化索引 │
│ ② 改写 SQL(避免函数、隐式转换等) │
│ ③ 修改表结构(加冗余字段、拆分表等) │
│ ④ 业务逻辑优化(减少查询频次、缓存) │
└──────────────────┬───────────────────────────────┘
▼
┌──────────────────────────────────────────────────┐
│ Step 5: 验证效果 │
│ 再次 EXPLAIN 确认执行计划变了 │
│ 实际执行查看耗时 │
│ 观察慢查询日志不再记录 │
└──────────────────────────────────────────────────┘二、典型案例
案例1:索引失效
sql
-- 有索引的列上用了函数
SELECT * FROM orders WHERE DATE(create_time) = '2024-01-01';
-- EXPLAIN: type=ALL, rows=500000
-- 优化后: 用范围查询替代函数
SELECT * FROM orders
WHERE create_time >= '2024-01-01' AND create_time < '2024-01-02';
-- EXPLAIN: type=range, rows=200案例2:隐式类型转换
sql
-- phone 列是 VARCHAR,但传入的是数字
SELECT * FROM users WHERE phone = 13800138000;
-- 隐式转换导致索引失效
-- EXPLAIN: type=ALL
-- 优化后: 用字符串查询
SELECT * FROM users WHERE phone = '13800138000';
-- EXPLAIN: type=ref案例3:大分页查询
sql
-- MySQL 需要扫到 offset+limit 行再丢弃
SELECT * FROM orders ORDER BY id LIMIT 100000, 20;
-- 优化后: 基于游标的分页
SELECT * FROM orders WHERE id > 100000 ORDER BY id LIMIT 20;三、常用诊断命令
sql
-- 当前正在运行的查询
SHOW PROCESSLIST;
SELECT * FROM performance_schema.processlist;
-- 查看超过 3 秒的查询
SELECT * FROM sys.processlist
WHERE conn_id > 0 AND time > 3;
-- 查看访问最多的表
SELECT * FROM sys.schema_table_statistics
ORDER BY rows_fetched DESC;
-- 查看没有用索引的查询
SELECT * FROM sys.statements_with_full_table_scans;📚 相关链接
- EXPLAIN 详解:**EXPLAIN与查询优化**
- 索引优化:**索引优化策略**
- Buffer Pool:**Buffer Pool配置与优化**
- ← 返回 **性能调优索引**