如果一个表在刚创建时没有慢 SQL,后面突然出现了慢 SQL,怎么处理?
这是一个非常典型的数据库性能“突刺”问题。刚创建时快,说明表结构索引设计没问题;突然变慢,说明“环境变量”变了。
处理这类问题必须分两步走:先“救火”止损,后“查因”根治。以下是标准处理SOP(以MySQL为例,原理通用):
第一步:应急止血(先恢复业务)
如果慢SQL正在拖垮线上业务,不要犹豫,立即执行:
- 杀掉慢查询会话:
执行
SHOW PROCESSLIST;找到处于Sending data或Creating sort index状态且耗时久的Id,执行KILL [Id];。 - 紧急绑定执行计划(SQL Plan Baseline):
如果业务无法重启且SQL高频调用,立即使用
USE INDEX或FORCE INDEX强制走索引,或者通过 SQL Hint(如 Oracle 的 Outline / MySQL 8.0 的 Query Rewrite Plugins)把执行计划固定住。 - 临时扩容/限流:若CPU飙高,临时升级实例规格,或在网关层对该API进行限流,防止雪崩。
第二步:深度诊断(核心四板斧)
止血后,按以下顺序排查根本原因,90%的问题都集中在前三斧:
1. 统计信息过期(最可能的第一嫌疑人)
表刚创建时数据量小,全表扫描和走索引代价差不多。随着数据增长,**优化器依赖的“统计信息”**若未及时更新,会误判表只有几百行,从而选择错误的索引(或不用索引)。
- 验证:执行
EXPLAIN [慢SQL],观察rows估算值是否严重偏离实际行数。 - 处理:执行
ANALYZE TABLE [表名];手动更新统计信息,让优化器重新计算索引基数(Cardinality)。这是最温和且见效最快的手段。
2. 索引失效(隐式类型转换或函数破坏)
SQL没变,但表字段变了,或者传入的参数变了。
- 隐式转换:
WHERE phone = 13800138000,但phone字段是varchar类型,导致索引列被隐式转为数字,索引失效。 - 函数操作:
WHERE DATE(create_time) = '2026-06-17',对索引列用了函数,导致无法走索引。 - 处理:修正应用传参类型,或改为范围查询(
create_time >= '...' and < '...')。
3. 数据倾斜(直方图缺失)
传入的参数值分布不均。例如 status 字段索引,大多数是 1(已完成),少量是 0(待处理)。以前查 0 很快,现在查 0 过滤出大量数据,优化器错误地选择了回表代价更大的索引。
- 处理:若MySQL 8.0,可创建直方图(
ANALYZE TABLE t UPDATE HISTOGRAM ON status);或者针对倾斜值单独改写SQL。
4. 锁等待与元数据锁(MDL)
SQL本身执行很快(0.01秒),但突然变慢(显示等待状态为 Waiting for table metadata lock)。
- 场景:有人对大表执行了
ALTER TABLE或OPTIMIZE TABLE未完成,或者长事务未提交,阻塞了所有对该表的DML/查询。 - 处理:查询
performance_schema.metadata_locks找到阻塞源,KILL掉持有锁的线程或DDL操作。
第三步:深度挖掘(执行计划对比)
务必对比“刚创建时”和“现在”的执行计划:
- 检查
Explain中的type是否从ref/range退化为了ALL(全表扫描)。 - 检查
Extra字段是否突然出现了Using temporary或Using filesort(说明排序内存不足或索引无法覆盖排序)。 - 检查索引选择性:执行
SHOW INDEX FROM [表名];,查看Cardinality(基数)。如果该值远小于表行数,说明该索引已失去区分度,应考虑新建联合索引或删除冗余干扰索引。
第四步:根治与防范(长效机制)
- 归档历史数据:如果表数据量已突破亿级,B+树高度从3层变为4层,IO次数增加。需做冷热分离,将旧数据迁移至归档表或历史库。
- 调整参数:增大
join_buffer_size或sort_buffer_size(如果排序慢);调整innodb_buffer_pool_size减少物理读。 - 监控告警:开启慢查询日志(
long_query_time=1),配置pt-query-digest定期分析;同时监控rows_examined(扫描行数)的环比突增,一旦超过阈值自动告警。
总结一句话:
先 ANALYZE TABLE 碰碰运气(命中率40%),再查 EXPLAIN 看索引选择(命中率80%),最后查 PROCESSLIST 看MDL锁(命中率95%)。 如果以上都无效,极大概率是业务并发量突然暴增导致资源争用(CPU/IO饱和),此时只能扩容或读写分离。