collstats 返回 storagesize(磁盘实际占用)、size(压缩后文档原始数据)、totalsize(数据+索引 storagesize 总和)、count(元数据缓存文档数);storagesize 常大于 size,因 wiredtiger 预留 padding、更新不即时回收空间、删除仅标记空闲 slot;分片集群中仅返回本地 shard 统计。

collStats 命令返回哪些关键空间指标
collStats 是 MongoDB 提供的聚合级诊断命令,直接返回集合在磁盘上的实际占用信息,不是逻辑文档大小总和。它返回的 storageSize、size、totalSize 容易混淆:
-
size:所有文档原始 BSON 数据(不含索引)的字节数,受压缩影响(如启用zstd时显著小于未压缩值) -
storageSize:该集合数据文件在磁盘上实际占用的空间,含 padding、碎片、未复用的已删除空间 -
totalSize:storageSize+ 所有相关索引的storageSize总和 - 注意:
count字段是文档数量,但不等价于db.collection.countDocuments({})—— 它读的是元数据缓存,可能滞后于实时写入(尤其 WiredTiger 在高并发写入后未及时刷新)
执行 collStats 的正确语法与权限要求
必须在目标集合所在数据库上下文中运行,且用户需具备 collStats 动作权限(通常由 clusterMonitor 或自定义角色授予)。错误示例:db.runCommand({collStats: "users"}) 在 admin 库执行会报 ns does not exist。
- 正确方式:
use myapp_db后执行db.runCommand({collStats: "users"}) - 若要包含详细索引统计,加
scale: 1024(单位转为 KB):db.runCommand({collStats: "logs", scale: 1024}) - 在分片集群中,
collStats只返回当前 mongos 路由到的 chunk 所在 shard 的局部统计,不是全局总和;需用sh.status()或db.adminCommand({listShards: 1})配合逐个 shard 查询
storageSize 明显大于 size 的常见原因
这是高频困惑点——明明只有 100MB 文档,storageSize 却显示 320MB。根本原因在于 WiredTiger 存储引擎的物理组织机制:
- WiredTiger 默认预留 padding(通过
block_compressor和prefix_compression影响),用于减少文档增长时的重写开销 - 执行过大量
$push、$set或就地更新后,旧空间不会立即回收,storageSize不自动收缩 - 删除文档只标记为空闲 slot,不触发即时空间释放;需手动运行
compact命令(仅支持 WiredTiger,且会阻塞写入) - 如果集合启用了 TTL 索引并刚批量过期删除,
storageSize下降会有延迟(后台线程清理)
快速估算整个数据库磁盘占用的实用组合
单靠 collStats 查每个集合太慢。更高效的做法是结合 db.stats() 和遍历集合:
-
db.stats({scale: 1024*1024})返回数据库级汇总(dataSize、storageSize、numCollections),单位 MB,响应快 - 需要明细时,用脚本遍历:
db.getCollectionNames().forEach(coll => { const res = db.runCommand({collStats: coll, scale: 1024*1024}); print(`${coll}: ${res.storageSize.toFixed(2)} MB`); }) - 注意:
db.stats()的storageSize是所有集合storageSize之和,但不含系统集合(如system.indexes)的开销,真实磁盘占用略高
真正影响磁盘的是 storageSize,而不是文档内容大小;频繁小更新的集合容易积累碎片,定期 compact 或重建索引(db.collection.reIndex())比单纯看 size 更能反映优化空间。











