先说说为啥要重建索引。简单讲,索引用久了会“散架”。比如频繁的增删改操作,会让索引页出现空洞,数据物理顺序混乱,甚至导致索引统计信息过期。MySQL优化器依赖这些统计信息来选执行计划,如果信息不准,它可能选错索引,直接拖慢查询。举个例子,有个订单表每天新增几十万条,原本走索引的范围查询,突然变成了全表扫描——一查才知道,索引基数(cardinality)估值偏差太大。这时候,光靠更新统计信息可能不够,必须彻底重建索引。
MySQL重建索引主要有两种方式:隐式重建和显式重建。隐式重建是通过命令实现的,它相当于对表做一次“大扫除”——不仅重建索引,还会整理数据碎片,相当于InnoDB的碎片整理工具。执行起来很简单:
但要注意,这命令会锁表,写操作会被阻塞,所以最好在业务低峰期干。另外,对于InnoDB引擎,本质上是将表数据导出一遍再导入,磁盘空间不够的话可能爆掉,务必提前检查。
显式重建更灵活,适合针对性优化。比如单独重建某个索引,可以用:
先删后建,相当于重新生成索引树。这种方法能精准控制,但缺点是删除索引期间,依赖这个索引的查询会全表扫描,如果表太大,临时性能抖动会很吓人。我曾经在午间流量低时操作一个亿级用户表,结果删除索引瞬间,CPU直接飙满——后来学乖了,先用工具在线操作,避免锁表。
什么时候该重建索引?别盲目!通常有几个信号:一是查询明显变慢,用看到“Using filesort”或“Using temporary”频繁出现;二是索引碎片率超过20%(用里的字段估算);三是大量批量删除后,索引空间没释放。但频率也别太高,否则反而增加负载。我们团队习惯每月低峰期整体巡检一次,结合监控脚本抓取慢查询日志,针对性重建。
重建策略得看业务场景。如果是OLTP高频交易系统,可以用分阶段重建:先建一个隐藏索引(MySQL 8.0支持不可见索引),测试无误后再切过去。没这功能的话,就建冗余索引——比如新增一个,数据同步完再重命名替换。对于分区表,还能按分区逐个重建,减少锁范围。记得有一次重建日志表索引,因为没分区,直接锁表半小时,客服电话都被打爆了……血泪教训啊!
重建后的优化也不容忽视。首先跑一遍更新统计信息,让优化器“认路”;其次用确认碎片率是否降到5%以内;最后压测关键查询,对比前后执行时间。我们常用sysbench模拟并发查询,观察QPS和延迟变化。还有个细节:重建后索引可能更紧凑,如果缓冲池(buffer pool)没预热,首次查询反而会慢。这时可以用强制走索引,或者提前加载热点数据到内存。
总之,索引重建不是银弹,而是权衡艺术。既要解决碎片问题,又得规避业务风险。核心原则就是:监控先行、低峰操作、有备无患。现在我们的数据库巡检清单里,索引健康度已是必查项,配合自动化脚本定期维护,总算告别了半夜被报警吵醒的日子。大家如果有更好的点子,欢迎拍砖补充!
3869

被折叠的 条评论
为什么被折叠?



