insertMany性能差或失败的根本原因是默认配置不合理:单次批量过大、写关注过严、连接池不足及缺乏超时控制;应分片(每批500–1000条)、设ordered: false、writeConcern: {w: 1, j: false}、timeoutMS,并调优连接池与索引。

直接用 insertMany 就行,但默认配置下容易卡住或丢数据——关键在批量大小、写关注和连接配置上。
为什么 insertMany 会慢甚至失败?
常见现象是插入中途卡死、超时、部分成功、或报 NetworkError / WriteConcernError。根本原因不是函数本身,而是:MongoDB 默认一次发太多文档(比如 10 万条),超出 socket 缓冲区;驱动默认等待所有节点确认写入(w: "majority"),而副本集同步慢;没控制并发,压垮服务端内存或连接数。
- 单次
insertMany不建议超过 1000 条文档(尤其文档较大时) - 避免在插入前未关闭索引——大批量写入期间禁用非必要索引,插完再建
- 确保连接字符串带
?maxPoolSize=20(默认 10,高并发时不够)
insertMany 的关键参数怎么设?
不传选项就是默认行为,但生产环境必须显式控制:
- 用
{ ordered: false }:某条失败不影响其余插入,适合容忍脏数据的导入场景 - 用
{ writeConcern: { w: 1, j: false } }:只等主节点写入完成,不等 journal 刷盘,速度提升明显(牺牲极小概率宕机丢失) - 加
timeoutMS防止挂死:{ timeoutMS: 30000 }
示例:collection.insertMany(docs, { ordered: false, writeConcern: { w: 1, j: false }, timeoutMS: 30000 })
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
大文件导入时怎么分批?
别把整个数组塞进一个 insertMany。按 chunk 切分 + 串行或有限并发执行更稳:
- 用
Array.prototype.slice()每次取 500–1000 条,避免内存爆掉 - 用
for...of串行提交(最简单,不易出错) - 若要并发,用
Promise.allSettled()控制最多 3–5 个并发批次,别无脑Promise.all() - 每批后加
await new Promise(r => setTimeout(r, 10))微延时,缓解服务端压力
什么时候该换 bulkWrite?
当你需要混合操作(比如部分 insert、部分 upsert)、或需对每条指定不同 writeConcern 时,bulkWrite 更灵活。但它比 insertMany 多一层封装开销,纯插入场景没必要硬切。
-
bulkWrite的ordered: false和insertOne组合,语义等价于insertMany(..., { ordered: false }) - 如果文档里有唯一键冲突风险,
upsert: true在updateOne中更可控 - 注意:老版本驱动(bulkWrite 错误堆栈不友好,升级到 v5+ 再用
真正容易被忽略的是:批量插入后,insertedIds 返回的是 ObjectId 数组,但如果你依赖 _id 做后续关联(比如写 metadata 表),得提前确认这些 ID 是否已生成并可用——MongoDB 确实会在客户端生成,但别假设它们一定按你传入顺序排列在 insertedIds 对象里。

















