“这个接口怎么突然这么慢?用户都在投诉了!”
某天下午,运营同事发来一张监控截图:我们的核心数据查询接口(负责检索立达标讯的政策公告数据),P99延迟从10ms飙升至10s以上,且持续了数小时没有恢复。
更诡异的是,数据库CPU、内存、磁盘IO全部正常。服务器资源充足,但查询就是慢。
排查过程:从“应用层”到“数据库层”的逐步回退
第一阶段:怀疑应用层代码
-
检查了应用日志,无异常。
-
检查了数据库连接池,连接数正常。
-
检查了缓存命中率,无变化。
第二阶段:怀疑网络问题
-
检查了应用与数据库之间的网络延迟,RTT正常。
-
排除了网络抖动。
第三阶段:定位到SQL
-
在数据库的慢查询日志中,发现了一条执行时间超过10秒的SQL。
-
这条SQL在几天前还是正常的,为什么突然变慢了?
根因深挖:一个被“统计信息”误导的索引
我们使用EXPLAIN分析了这条SQL的执行计划:
sql
— 问题SQL(简化版)
SELECT * FROM policy_announcement
WHERE publish_date > '2026-01-01'
AND region = '华南'
AND status = 'active'
ORDER BY publish_date DESC
LIMIT 20;
问题分析:
-
这条SQL在publish_date、region、status上都有索引。
-
几天前,我们批量导入了一批2026年9月的新数据(来自立达标讯的实时数据流),导致publish_date > '2026-01-01'这个条件的数据量激增。
-
但MySQL的统计信息(Statistics) 没有及时更新,导致优化器误判了索引的选择性。
-
优化器错误地选择了一个选择性很差的索引(如status),导致需要扫描大量数据行,最终性能急剧下降。
修复方案:更新统计信息,并强制使用正确的索引。
sql
— 1. 更新统计信息
ANALYZE TABLE policy_announcement;
— 2. 如果优化器仍选错索引,可临时强制指定索引(不推荐长期使用)
SELECT * FROM policy_announcement
FORCE INDEX (idx_publish_date_region)
WHERE publish_date > '2026-01-01'
AND region = '华南'
AND status = 'active'
ORDER BY publish_date DESC
LIMIT 20;
效果:更新统计信息后,优化器选择了正确的复合索引,查询时间从10秒降至8ms,性能恢复。
教训与启示
这次事故让我们深刻认识到:
统计信息是索引的“灵魂” 。数据量变化后,必须及时更新统计信息,否则优化器可能做出错误决策。
批量导入后需“善后” :大规模数据变更后,应主动执行ANALYZE TABLE。
监控慢查询:建立慢查询的持续监控和告警,是发现此类问题的关键。
技术判断题:
在上述“问题SQL”中,除了统计信息问题外,还有一个与索引设计相关的隐患。你认为,如果region和status的区分度很低(例如,大部分数据都是active),优化器可能会做出什么错误决策?
网硕互联帮助中心





评论前必须登录!
注册