MySQL索引不会因DELETE失效,但大量删除会导致B+树出现空洞页、统计信息陈旧,引发执行计划劣化;需通过INNODB_INDEX_STATS和SHOW INDEX验证统计准确性,再决定是否重建。
大规模 DELETE 后为什么索引“变慢”而不是“失效”
MySQL 的索引不会因
操作而“失效”,但大量删除(尤其非顺序、高比例删除)会导致 B+ 树索引出现大量“空洞页”(empty pages)、页分裂不均、统计信息陈旧,最终表现为查询执行计划劣化(如误选全表扫描)、
显示
严重高估、
异常变小等现象。本质是数据物理分布碎片化 + 优化器统计失真。
判断是否需要重建索引:看
和
别凭感觉——先验证。重点查两处:
—— 关注
(唯一值估算)是否远低于实际,
是否异常高(说明空洞多)
—— 对比
列与实际唯一值数量;若
接近 0 或恒为 1,且表有主键/唯一索引,大概率统计已过期
执行
后再查,若
无明显变化,说明采样不足或数据分布极端,需强制更新统计
重建索引的三种方式:何时用
,何时用
,何时必须
三者都触发重建,但行为和适用场景不同:
MySQL(Linux)
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
下载
:对 InnoDB 表等价于
+ 更新统计;会锁表(8.0+ 可在线,但仍有 DML 阻塞窗口),适合中小表(
或
:显式重建聚簇索引,释放空洞页,重排数据物理顺序;8.0 支持
(默认),但仍需额外磁盘空间(≈原表大小)
:仅重建单个二级索引,不影响聚簇索引;适合某索引严重退化但主键/聚簇结构尚可时;注意:
瞬间释放空间,
期间该列无法走索引
避免重复踩坑:重建不是万能解,关键在删除策略本身
频繁重建索引治标不治本。真正要控制的是删除方式:
禁用
批量删千万级数据——改用分批 +
+ 延迟提交,例如:
,每批后
减压
若删除比例 >30%,优先考虑
+
切换,比
+
更快更干净
定期(如每周)跑
,但对超大表(>100GB)慎用默认采样;可通过
提高采样精度(需
)
重建索引本身不难,难的是判断“到底要不要建”以及“删的时候就别让它碎”。物理碎片和统计偏差往往并存,但修复顺序一定是:先确认统计是否失真 → 再决定是否重建 → 最后回溯删除逻辑是否合理。
DELETEEXPLAINrowskey_leninformation_schema.INNODB_INDEX_STATSSHOW INDEXSELECT * FROM information_schema.INNODB_INDEX_STATS WHERE table_name = 'your_table' AND database_name = 'your_db';n_diff_pfx01n_leaf_pagesSHOW INDEX FROM your_table;CardinalityCardinalityANALYZE TABLE your_table;CardinalityOPTIMIZE TABLEALTER TABLE ... FORCEDROP + ADDOPTIMIZE TABLE your_table;ALTER TABLE ... FORCEALTER TABLE your_table ENGINE=InnoDB;ALTER TABLE your_table FORCE;ALGORITHM=INPLACEDROP INDEX idx_name ON your_table; ADD INDEX idx_name (col);DROPADDDELETE FROM t WHERE ...LIMITDELETE FROM t WHERE id BETWEEN ? AND ? LIMIT 10000;SLEEP(0.1)CREATE TABLE new_t AS SELECT ... FROM old_t WHERE keep_condition;RENAMEDELETEOPTIMIZEANALYZE TABLESET GLOBAL innodb_stats_persistent_sample_pages = 200;innodb_stats_persistent=ON