预分片必须在写入前用sh.splitAt()对空集合按哈希空间等分切点,否则千万级导入会卡死在首个shard;需配合bulkWrite+unordered才能实现并发路由与均匀写入。
不做预分片,千万级导入基本卡死在第一个 shard 上——这不是配置问题,是 MongoDB 的 chunk 初始化机制决定的。
一旦集合里有任意一条文档,sh.splitAt() 就可能失败或被 balancer 中断。MongoDB 不允许对已有数据的 chunk 边界做“插队式”拆分;它只接受在空集合上预先规划好 chunk 范围。你看到 sh.status() 里 chunks 行只显示 1 个、且全部落在 shard0000,说明已经错过窗口期。
sh.status(),看 chunks 行是否为 1,以及 balancer 状态是否为 OK(不是 Running 或 Stopping){_id: "hashed"})比范围分片更适配预分片,因为边界值可精确计算,无热点偏移风险以 8 个 shard 为例,哈希空间是 64 位有符号整数(-2^63 到 2^63-1),总跨度为 2^64。每份 chunk 宽度 = 2^64 / 8 = 0x2000000000000000,切点就是从 0x2000000000000000 开始,每次加这个值,直到 0xE000000000000000(共 7 个切点)。
NumberLong 格式):for i in range(1, 8): print(hex(i * 0x2000000000000000))
sh.splitAt("db.coll", {_id: NumberLong("0x2000000000000000")})
sh.status() 验证:确认 chunks 总数为 8,且每个 shard 下至少有 1 个 chunk(不是全堆在同一个 shard)预分片只是铺好了路,如果客户端还串行发写请求,mongos 仍可能把请求都打到同一个 shard 上。必须配合无序批量写入,才能触发 mongos 并行路由。
ordered: false(Node.js、PyMongo、Java Driver 均支持)mongoimport 默认是有序写入,且无法控制 ordered 参数;它底层调用的是单文档插入,不是 bulkWrite
bulkWrite + ordered: false 比 mongoimport 快 3–5 倍,CPU 利用率在所有 shard 均匀分布writeErrors 字段预热对首次查询延迟敏感的场景有用,但对纯写入优化无效。如果你刚导入完就立刻跑大量聚合或索引构建,db.runCommand({touch: "coll", data: true, index: true}) 能减少磁盘 IO 颠簸。
millis 字段,data 和 indexes 都应有毫秒级耗时,否则说明文件没加载成功最容易被忽略的是:预分片切点必须严格按哈希空间等分,少一个切点,就少一个初始 chunk,剩余数据仍会堆积在最后一个未 split 的 chunk 上——哪怕你算错了 1 个 bit,整个预分片就失效了。
逐浪 · 第十一篇: Vibe Coding 下的效率定义与规范建设
硅谷大佬都在聊的 Loop Engineering:到底在卷什么?
BoxAgnts 工具系统(6):多 Provider 适配与 Agent 查询循环
同行月球逃脱船员舱隐藏物资位置一览
AI Coding框架:打好TDD和SDD这两拳
从 PDD DDD SDD 到 TDD:我是如何用一套 Agent 工程方法论推进 My-Notion 的