bulk_write是性能分水岭,10万条数据可从200秒降至3–8秒;支持混合操作、per-operation write_concern、ordered=false并发执行,但需检查writeerrors;批次大小应据bson体积动态调整,避免超16mb限制。

直接用 bulk_write,别用循环 insert_one 或 update_one —— 这不是“建议”,是性能分水岭。10 万条数据,单条写要 200 秒以上,bulk_write 分批后通常压到 3–8 秒。
为什么 bulk_write 比 insert_many 更值得细调
insert_many 是 bulk_write 的简化封装,它默认 ordered=True,且不支持混合操作;而 bulk_write 可以在同一请求里混用 InsertOne、UpdateOne、DeleteOne,还能为每条操作单独设 upsert 和 write_concern。真正需要按业务逻辑差异化控制写入行为时,绕不开 bulk_write。
- 想给一批用户补字段,另一批用户删记录?
insert_many做不到,必须用bulk_write - 部分数据要等主从同步(
w: "majority"),部分只要主节点落盘(w: 1)?只有bulk_write支持 per-operation 级别的write_concern - 误设
ordered=True后某条文档因唯一键冲突失败,整批后续全跳过——这种静默丢数据,在日志类场景里极难排查
ordered=False 不是开箱即用的加速器,得配错误检查
设 ordered=False 后,MongoDB 会并发执行所有操作,失败项不影响其余项,但错误不会抛异常,而是塞进返回值的 writeErrors 字段里。不主动读这个字段,就等于把失败当成功。
- 必须检查
result.writeErrors,尤其在 ETL 或埋点写入中,漏掉几百条失败文档可能几周都发现不了 - 在分片集群中,
ordered=False才能让mongos并行投递到多个分片;ordered=True是串行路由,天然卡瓶颈 - PyMongo 默认是
ordered=True,Node.js 驱动也一样,不显式传参就不是“无序”
批次大小别硬套“1000”,先看单条 BSON 体积
批次大小不是越大越好,关键约束是单个请求体不能超 MongoDB 的 BSON 16MB 上限。如果单条文档平均 5KB,那 3000 条就接近 15MB,再加点元数据就超限;若文档含大字段(如 base64 图片),300 条就可能爆。
- 实测安全区间是 100–500 条/批:小于此数,网络节省不明显;大于此数,容易触发
DocumentTooLarge或服务端 OOM - 不要一次性构造全部
requests列表再传给bulk_write,边查边攒、攒够一批就发一批,避免客户端内存暴涨 - 对更新类操作,优先用
UpdateMany替代多个UpdateOne;后者每条都要独立 filter,解析开销翻倍
write_concern 必须按数据等级显式设,别信“默认”
副本集里写入慢,80% 是因为 write_concern 卡在等多数节点确认。全局配 w: "majority" 看似安全,但某个从节点延迟高或 oplog 追不上,整个 bulk_write 就卡住直到超时(默认 30 秒)。
- 日志、埋点类数据:显式传
write_concern={"w": 1},只等主节点 journal 落盘,延迟稳定在毫秒级 - 订单、账户类关键数据:才用
{"w": "majority"},但必须确保所有从节点oplogSize≥ 24 小时变更量 - 千万别省略
write_concern参数——生产环境配置可能覆盖驱动默认值,不写等于裸奔
真正卡住性能的,往往不是 bulk_write 本身,而是没意识到它暴露了底层链路的所有隐性依赖:网络延迟、副本同步状态、BSON 大小、客户端内存、甚至 WiredTiger 的 journal 刷盘节奏。调参前先看清数据特征和部署拓扑,比盲目加大批次更管用。
大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!











