MongoDB默认chunk size为64MB,是兼顾写入放大、迁移开销与均衡响应的平衡值;小于32MB易致元数据压力大,大于128MB则迁移耗时长、易超时阻塞写入。

Chunk Size 设置为 64MB 是 MongoDB 默认且最稳妥的起点
MongoDB 官方将 chunkSize 默认设为 64(单位 MB),这不是随意定的。它在写入放大、迁移开销、负载均衡响应速度之间做了平衡。小于 32MB 容易导致 chunk 过多,config servers 元数据压力上升;大于 128MB 则会让单次 moveChunk 操作耗时过长,阻塞写入、拖慢自动均衡,尤其在高吞吐场景下可能触发 Failed to move chunk 或 Timeout while waiting for a response from the shard。
除非你有明确观测依据,否则不要一上来就调小或调大。实操建议:
- 新集群上线前,先用默认
64运行至少 2–3 天,观察sh.status()输出中的chunks数量增长趋势和各 shard 的balancer活动频率 - 若单个集合长期只有 1–2 个 chunk,说明数据分布严重不均,此时调小
chunkSize不解决问题——应检查分片键选择是否合理,比如用了单调递增的_id或时间戳字段 - 修改需通过
sh.setBalancerState(false)暂停均衡器,再执行db.settings.updateOne({ _id: "chunksize" }, { $set: { value: 128 } }, { upsert: true }),完成后重启均衡器
什么情况下该调大 chunkSize?看迁移延迟和 writeConcern 超时
当你的写入峰值稳定在 5K+ ops/s,且频繁出现 moveChunk command failed: { code: 13137, codeName: 'CommandNotFound' } 或更常见的 moveChunk failed: { code: 9001, codeName: 'NetworkInterfaceExceededTimeLimit' },大概率是 chunk 太小、迁移太频繁,网络或磁盘 I/O 在迁移窗口内扛不住。
这时可逐步上调:128 → 256,但必须同步满足两个条件:
- 所有 shard 的磁盘空闲空间 ≥ 单个 chunk 最大预估体积 × 2(迁移期间旧 chunk 未删、新 chunk 已写)
- 应用端
writeConcern不能设为{ w: "majority", j: true }且超时wtimeoutmoveChunk 期间部分写请求会因 majority 确认失败而报WriteConcernFailed - 调大后需用
db.collection.stats().sharded验证平均 chunk 大小是否趋近目标值;若仍大量卡在32–48MB,说明数据写入模式(如批量插入大小不稳定)或分片键散列度不足
动态调整不是实时生效,chunk 拆分/合并靠实际写入驱动
chunkSize 只控制「未来新拆分」的阈值,不影响已有 chunk。MongoDB 不提供强制合并小 chunk 的命令,也不会主动把 20MB 的 chunk 和邻近 40MB 的 chunk 合并成一个 60MB 的 chunk。所谓“动态”,其实是靠持续写入触发自动拆分(split)来逼近目标大小。
这意味着:
- 刚改完
chunkSize,sh.status()显示的 chunk 分布不会立刻变化,要等后续 insert/update 触发 split 才逐步体现 - 如果你的集合写入量极低(比如每天只几百条),那 chunk 大小可能几个月都不变——此时手动干预无效,不如换分片键或考虑停用分片
- 想快速“重分布”,唯一可靠方式是导出 + 清空 + 按新分片键重建:用
mongodump --uri="..." --collection=xxx,再mongorestore --uri="..." --drop,但要注意业务停写窗口
真正需要关注的不是 chunkSize,而是 chunk 分布标准差
运维中常盯着 chunkSize 调优,但线上抖动往往来自 chunks per shard 的标准差过大。比如 4 个 shard,chunk 数分别是 [120, 122, 118, 280],即使平均 chunk 大小是 64MB,也会导致第 4 个 shard CPU 和磁盘持续过载。
比调 chunkSize 更有效的动作是:
- 每小时跑一次
sh.status().shards.map(s => ({ name: s, chunks: s.chunks })),算标准差,>30 就告警 - 查
db.collection.getShardDistribution(),确认热点是否集中在某个 tag-aware shard 上 - 如果分片键是复合字段,检查第二字段(如
{ region: 1, user_id: 1 })的取值离散度——user_id若大量重复(如 10 万用户共用 100 个 ID),就会让 chunk 拆分失效
chunkSize 只是杠杆支点,分片键设计才是力臂本身。支点挪两厘米没用,力臂歪了才真压垮集群。


















