分片集群容量评估必须跨分片聚合数据,因db.collection.stats()仅返回单个分片(如primary shard)的统计,非全量;应使用sh.getShardDistribution()或手动collStats命令获取各分片真实分布。

分片集群容量评估不能只看单个分片或 mongos 返回的 stats,必须跨分片聚合真实数据分布和资源水位。
为什么 db.collection.stats() 在分片集群里不准
在 mongos 上执行 db.collection.stats(),返回的 count、size、storageSize 等字段仅来自该集合的 primary shard(或当前路由到的某个分片),不是全量数据。这是最常被误读的点——你以为查的是整个集合,其实只看了 1/N。
- mongos 不会自动合并各分片的统计结果,它只是透传命令给一个分片并原样返回
- 若集合尚未分片(全部数据还在 primary shard),结果看似“完整”,但此时已不满足“分片集群评估”前提
- 真正启用分片后,
db.collection.stats()对容量评估基本无参考价值
用 sh.getShardDistribution() 快速获取各分片数据分布
这是 mongos 提供的专用函数,底层调用 collStats 命令向所有 shards 并行发起请求并汇总,结果包含每 shard 的文档数、数据大小、存储大小等关键指标。
- 执行方式:在 mongos shell 中先
use your_db_name,再运行sh.getShardDistribution("your_collection_name") - 输出字段包括
docs(文档总数)、dataSize(字节)、storageSize(磁盘占用)、chunks(chunk 数量),且按 shard 名自动排序 - 要求 MongoDB ≥ 4.2;某 shard 不可达时会跳过并警告,不影响整体执行
- 它不依赖集合是否已平衡,即使 chunk 分布严重倾斜也能反映真实现状
手动调用 collStats 兼容旧版本或需自定义字段
当使用 MongoDB avgObjSize、nindexes、indexCount 时,得自己遍历每个 shard 执行 collStats。
- 第一步:用
sh.status()或db.adminCommand({listShards: 1})获取 shard 列表 - 第二步:对每个 shard,连接其 mongod 实例(不是 mongos),例如:
mongo --host shard01:27018 - 第三步:在对应 shard 的 admin 数据库中执行:
db.runCommand({collStats: "your_db.your_collection", scale: 1024})(scale: 1024表示单位为 KB) - 注意:
collStats必须直连 shard 的 mongod,连 mongos 会报错command collStats requires authentication或返回空结果
容量评估必须结合 chunk 分布、I/O 和内存水位
光看数据量不够,还要确认 chunk 是否均匀、磁盘 I/O 是否承压、WiredTiger Cache 是否充足。
- 用
sh.status()查看每个 shard 的chunks数和迁移历史,若某 shard chunk 远多于其他,说明负载不均,可能即将触发自动迁移 - 检查各 shard 的磁盘使用率(
df -h)和 I/O wait(iostat -x 1),尤其在重写索引或重新分片前,I/O 容量需低于 50% - WiredTiger Cache 设置不能超过物理内存的 60%,否则易触发 OOM;可通过
db.serverStatus().wiredTiger.cache查看当前使用率 - 重新分片所需空间公式:每个 shard 至少需要
((collection size + index size) * 2) / shard count的可用空间
真正卡住容量评估的,往往不是数据总量,而是 chunk 分布不均导致的局部热点,以及 I/O 或内存配置没跟上数据增长节奏。这些细节在 sh.getShardDistribution() 输出里藏得不深,但需要你主动对照 sh.status() 和系统监控一起看。











