已采纳
回答正文
回复
讨论正文
该问题的正文、回答与讨论。
我负责一套物流轨迹系统的 MySQL 8.0.36(单主 32C128G,innodb_buffer_pool_size=96G),核心表 t_track 约 1.8 亿行、数据文件 320GB,删除密集——每天约 25% 的行被批量 DELETE(过 90 天归档),写入 QPS 日常 1800~2200(几乎全 INSERT,很少 UPDATE)。表上有 7 个二级索引(含 1 个覆盖索引),索引总量约 13GB。
跑了一个月后,一条按 idx_order_id 过滤 + 回表的查询 P99 从 18ms 涨到 47ms,QPS 没变、SQL 没变、buffer pool 命中率从 99.2% 掉到 89%。拉了 information_schema.INNODB_TABLESPACES 和 SHOW TABLE STATUS 对比:
Data_free 从初始 ~0 涨到 4.7GBSHOW INDEX + pt-duplicate-key-checker 没查到重复,手动抽样 SELECT COUNT(*) 和 SHOW INDEX 的 Cardinality 估算的)我初步判断是 InnoDB 二级索引在大量 DELETE 后,B+ 树页不主动合并/收缩,导致 buffer pool 里塞了大量"空页",命中率被稀释,回表 IO 也变多了。
idx_order_id + 回表,type=ref、rows 估算没变,只是实际 rows_examined 涨了 60%。SHOW ENGINE INNODB STATUS 里 Buffer pool hit rate 从 99.2% 掉到 89%,InnoDB_buffer_pool_pages_total 没变,但 InnoDB_buffer_pool_pages_data 没怎么涨——说明"脏页"占比在涨。Rows_examined 从 ~12 涨到 ~28,确认是索引页稀疏导致回表时多读了几页。Data_free / (Data_free + Data_length) 超过多少,就该触发 OPTIMIZE / ALTER TABLE ... FORCE?我现在的 40% 算不算"该动了"?OPTIMIZE TABLE(INPLACE)和 pt-online-schema-change 这两种方式,对写入 QPS 的影响分别大概是什么量级?有没有人实测过"重建期间写 P99 从 8ms 涨到多少 ms"?PARTITION + 按时间分区 DROP PARTITION,或者把"删除"改成"软删 + 归档表",哪种对 1.8 亿行、90% 写入的场景更划算?希望拿到:① 一个可落地的"该不该重建"判断清单(哪几个指标、阈值大概多少);② 重建方式选型(INPLACE vs pt-osc)的写影响量化数据;③ 如果"不重建"更划算,给一个具体的改造路径。
社区里已经有几篇相关经验(索引治理、页分裂阈值判断、change buffering 取舍),但"删除密集 + 高写入"这个组合下的"重建时机"我还没看到有人给过可量化的标准,想请教一下。