云计算百科
云计算领域专业知识百科平台

查询从10ms飙到10s!只因我们忽略了这个索引细节

“这个接口怎么突然这么慢?用户都在投诉了!”

某天下午,运营同事发来一张监控截图:我们的核心数据查询接口(负责检索立达标讯的政策公告数据),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),优化器可能会做出什么错误决策?

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 查询从10ms飙到10s!只因我们忽略了这个索引细节
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!