一、慢查询发生场景
聚合查询
多表查询
表数据量过大查询
深度分页查询
表象:页面加载过慢、接口压测响应时间过长(超过 1s;实际中 500ms 以上就值得关注)。
二、如何定位
1. 开启慢查询日志 —— 找到慢 SQL
-- 查看是否开启 SHOW VARIABLES LIKE 'slow_query_log'; -- 开启慢查询日志 SET GLOBAL slow_query_log = ON; -- 设置阈值(超过 1 秒算慢,建议调到 0.5~1 秒) SET GLOBAL long_query_time = 1; -- 查看日志文件位置 SHOW VARIABLES LIKE 'slow_query_log_file'; -- 可选:记录没走索引的 SQL(生产环境慎开,可能刷爆日志) SET GLOBAL log_queries_not_using_indexes = ON;开启后,超过阈值的 SQL 会被记录到日志文件。
2. 分析慢查询日志 —— 找出最该优化的
日志是纯文本,用工具聚合:
# MySQL 自带,按总耗时排序取前 10 mysqldumpslow -s t -t 10 slow.log # Percona 工具,分析更强大(推荐) pt-query-digest slow.log它们能告诉你:哪条 SQL 执行次数最多、总耗时最长、平均耗时最高。
3. 实时查看正在执行的慢 SQL
-- 看当前正在跑的查询 SHOW PROCESSLIST; -- 或查 information_schema,筛出执行超过 1 秒的 SELECT * FROM information_schema.processlist WHERE time > 1;4. 监控工具(生产环境常用)
SkyWalking、Arthas:APM 工具,从应用层定位到具体 SQL
5. 用 EXPLAIN 分析 —— 判断为什么慢(最关键)
EXPLAIN SELECT * FROM orders WHERE user_id = 123;重点看这几列:
| 列 | 含义 | 关注点 |
|---|---|---|
| type | 访问类型 | 从好到坏:system > const > eq_ref > ref > range > index > ALL。出现ALL(全表扫描)要警惕 |
| key | 实际用的索引 | 为NULL说明没走索引 |
| rows | 预估扫描行数 | 越大越慢,接近全表行数越危险 |
| filtered | 过滤后剩余百分比 | 越低说明扫了很多无效行 |