1. 选择合适的存储引擎
MongoDB默认使用WiredTiger存储引擎(推荐),其内置压缩功能可显著减少磁盘空间占用(相比旧版MMAPv1引擎,WiredTiger的压缩率更高,且支持文档级并发控制)。若需读取密集型场景(如历史数据归档),可保留WiredTiger;若为写入密集型且无需压缩(如日志数据),可考虑MMAPv1,但需注意其不支持文档级压缩。
2. 配置WiredTiger压缩参数
通过调整WiredTiger的压缩算法和级别,平衡压缩率与CPU开销:
- 压缩算法选择:
snappy(默认):压缩率约2:1,CPU开销低,适合写入密集型业务(如实时数据上报);zstd(推荐):压缩率约4:1(高于snappy),CPU开销中低,解压缩速度快于zlib,适合读取密集型业务(如报表查询、数据分析);zlib:压缩率约3:1,CPU开销高,适合存储敏感且读取低频的场景(如历史归档数据);none:禁用压缩,仅适用于数据本身不可压缩(如二进制文件,如图片、视频)。
- 配置方法:在
/etc/mongod.conf中修改以下参数:修改后重启MongoDB服务使配置生效:storage: engine: wiredTiger wiredTiger: collectionConfig: blockCompressor: zstd # 设置集合压缩算法 engineConfig: cacheSizeGB: 4 # 缓存大小设置为服务器内存的40%-75%(默认值可能较小,需根据实际情况调整)sudo systemctl restart mongod。
3. 使用compact命令整理碎片并回收空间
WiredTiger引擎下,删除数据后空间不会自动释放,需通过compact命令重建集合,回收未使用的空间:
- 语法:
db.runCommand({ compact: "collection_name", compression: "zstd" })(compression参数可选,指定压缩算法); - 注意事项:
- 需在主节点执行;
- 会阻塞集合的读写操作,建议在低峰期执行;
- 对于分片集群,需在每个分片上分别执行。
4. 用repairDatabase命令修复并压缩整个数据库
若compact命令无法满足需求(如数据库严重碎片化),可使用repairDatabase命令重新分配所有集合的空间,剔除未使用的部分:
- 语法:
db.runCommand({ repairDatabase: 1 }); - 注意事项:
- 需要双倍磁盘空间(修复过程会创建临时文件);
- 需在单节点模式下执行(副本集需先停止 secondary 节点,主节点降级为 secondary 后执行);
- 推荐在维护窗口期操作,避免影响业务。
5. 通过mongodump/mongorestore备份重建
若上述方法仍无法有效收缩磁盘空间,可通过备份+恢复的方式彻底重建数据库:
- 步骤:
- 导出数据:
mongodump --db your_database_name --out /path/to/backup; - 删除原数据库:
mongo --eval "db.dropDatabase()"; - 恢复数据:
mongorestore /path/to/backup/your_database_name;
- 导出数据:
- 优势:恢复后的数据库无碎片,空间占用更小;
- 注意事项:操作前需备份重要数据,避免数据丢失。
6. 优化数据模型设计
不合理的数据模型会导致存储空间浪费,需遵循以下原则:
- 避免过大文档:MongoDB的BSON文档大小限制为16MB,超过需拆分(如将大文档拆分为多个小文档,通过引用关联);
- 使用嵌入式文档:将关联数据嵌入父文档(如“订单”文档中嵌入“订单项”),减少关联查询的开销;
- 合理使用索引:为常用查询字段创建索引(如
db.collection.createIndex({ field: 1 })),但避免过度索引(每个索引都会占用存储空间,可通过db.collection.stats().indexSizes查看索引大小)。
7. 定期清理无用数据
- 删除过期数据:使用
remove或deleteMany命令删除不再需要的数据(如db.collection.remove({ "status": "inactive", "createdAt": { $lt: ISODate("2024-01-01") } } })); - 归档历史数据:将历史数据迁移到低成本存储(如对象存储OSS、冷数据仓库),保留MongoDB中的精简数据集;
- 监控数据增长:定期执行
db.stats()(查看数据库存储使用情况)和db.collection.stats()(查看集合存储使用情况),及时发现异常增长。
8. 管理日志文件大小
MongoDB的日志文件(默认路径:/var/log/mongodb/mongod.log)会持续增长,需通过以下方式控制:
- 日志切割:使用
logrotate工具配置自动切割(示例配置):将上述配置保存为/var/log/mongodb/mongod.log { daily # 每天切割 rotate 7 # 保留7天 size 100M # 单个文件最大100MB compress # 压缩旧日志 missingok # 文件不存在时不报错 notifempty # 文件为空时不切割 copytruncate # 复制后清空原文件(避免重启服务) }/etc/logrotate.d/mongodb,系统会自动执行切割; - 调整日志级别:通过
systemLog.verbosity参数控制日志详细程度(默认0,设置为1可输出更多诊断信息,但会增加日志量); - 手动切割:执行
db.runCommand({ logRotate: 1 })命令,无需重启服务。