delete/remove后磁盘空间不下降不是bug,是WiredTiger引擎设计使然:仅标记空间为可复用,不返还OS;compact需加force:true才回收索引空间,且执行前须确认主节点、清理孤儿chunk、预留≥1.2倍磁盘余量。

为什么 delete/remove 后磁盘空间不下降
这不是 bug,是 WiredTiger 引擎的正常行为:删除只标记空间为 available for reuse,不归还 OS。执行 db.collection.deleteMany({}) 或 remove() 后,df -h 看不到变化,db.collection.stats().totalSize 也几乎不变——因为底层 .wt 文件没被重写。
关键指标是 wiredTiger.block-manager.file bytes available for reuse,它告诉你当前有多少字节可复用。值越大,说明碎片越严重。
compact 命令到底回收不回收索引空间
默认 db.runCommand({compact: "mycol"}) 不保证索引文件被重写,尤其在 4.4 以前版本,索引 indexSize 往往纹丝不动。必须加 force: true 才能强制重建索引结构。
-
force: true是显式开关,不是默认行为;不加它,compact 可能只整理数据文件 - 复合索引、文本索引、TTL 索引都受
force: true影响,实测索引体积下降 20%–60% - 执行后立刻查
db.mycol.stats().indexSize和系统级ls -lh *.wt,才能确认是否真收缩
执行 compact 前必须验证的三件事
跳过任何一项,compact 要么失败,要么白跑:
- 确认连接的是
primary:运行rs.isMaster().ismaster,必须返回true;secondary 上执行无效 - 检查
fs.files和fs.chunks是否有孤儿数据:如果只删了fs.files文档却漏清对应fs.chunks,compact 完全扫不到那些 chunk,空间照占 - 磁盘余量 ≥ 原集合
totalSize的 1.2 倍:compact 期间会并行写新 .wt 文件,临时空间峰值很高
TTL 索引删除后要不要 reIndex
要。TTL 后台线程清理文档时,可能残留元数据干扰空间回收逻辑。即使 compact 成功,也建议紧接着跑一次 db.mycol.reIndex()。
注意:reIndex() 会阻塞写入,且不能在 compact 过程中并发执行;它不解决碎片,只清理索引元数据状态,防止后续统计失真或扫描异常。
真正难的是权衡:compact 需要停写窗口和足够磁盘,repairDatabase 风险高且已废弃,而单纯依赖空间复用又可能让监控指标长期失真。别只盯着 df -h,得结合 available for reuse 和业务写入节奏做判断。

















