一、概述
MongoDB为客户端提供了批量执行写入操作的能力。批量写入操作影响单个集合。MongoDB允许应用程序确定批量写入操作所需的可接受确认级别。
db.collection.bulkWrite()方法提供了执行批量插入、更新和删除操作的能力。
MongoDB还支持通过db.collection.insertMany()方法进行批量插入。
二、有序操作与无序操作
批量写入操作可以是有序的,也可以是无序的。
通过有序的操作列表,MongoDB串行执行操作。如果在处理其中一个写入操作期间发生错误,MongoDB将返回,而不处理列表中的任何剩余写入操作。请参阅有序的批量写入
通过无序的操作列表,MongoDB可以并行执行操作,但不能保证这种行为。如果在处理其中一个写入操作期间发生错误,MongoDB将继续处理列表中的其余写入操作。请参阅无序批量写入示例。
在碎片集合上执行操作的有序列表通常比执行无序列表慢,因为对于有序列表,每个操作都必须等待前一个操作完成。
默认情况下,bulkWrite()执行有序操作。要指定无序写入操作,请在选项文档中设置ordered:false。
三、bulkWrite() 方法
bulkWrite()支持以下写入操作:
- insertOne
- updateOne
- updateMany
- replaceOne
- deleteOne
- deleteMany
每个写入操作都作为数组中的文档传递给bulkWrite()。
1、例
本节中的示例使用集合:pizzas
|---------------------------------------------------------------------------|
| db.pizzas.
insertMany( [
|
| {
_id:
0,
type:
"pepperoni",
size:
"small",
price:
4 },
|
| {
_id:
1,
type:
"cheese",
size:
"medium",
price:
7 },
|
| {
_id:
2,
type:
"vegan",
size:
"large",
price:
8 }
|
| ] )
|
下面的bulkWrite()示例在pizzas集合上运行这些操作:
-
使用insertOne添加两个文档。
-
使用updateOne更新文档。
-
使用deleteOne删除文档。
-
使用replaceOne替换文档。
try {
db.pizzas.bulkWrite( [
{ insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } },
{ insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } },
{ updateOne: {
filter: { type: "cheese" },
update: { $set: { price: 8 } }
} },
{ deleteOne: { filter: { type: "pepperoni"} } },
{ replaceOne: {
filter: { type: "vegan" },
replacement: { type: "tofu", size: "small", price: 4 }
} }
] )
} catch( error ) {
print( error )
}
示例输出,包括已完成操作的摘要:
{
acknowledged: true,
insertedCount: 2,
insertedIds: { '0': 3, '1': 4 },
matchedCount: 2,
modifiedCount: 2,
deletedCount: 1,
upsertedCount: 0,
upsertedIds: {}
}
四、批量插入到分片集合的策略
大容量插入操作,包括初始数据插入或例程 数据导入,可能会影响分片集群性能。为 批量插入时,请考虑以下策略:
五、预拆分集合
如果分片集合为空,则该集合只有 一个首字母块,它驻留在单个分片上。 然后,MongoDB必须花时间接收数据,创建拆分和 将拆分的块分发到可用的分片。为了避免这种情况 性能成本,您可以预先拆分集合,如在分片群集中拆分块。
六、无序写入mongos
要提高分片集群的写入性能,请使用bulkWrite()可选参数设置为 。orderedfalsemongos可以尝试将写入发送到 同时使用多个分片。对于空集合, 首先预先拆分集合,如在分片群集中拆分块。
七、避免单调限制
如果分片键在插入过程中单调增加,则所有 插入的数据将转到集合中的最后一个块,该块将 总是以单个分片结束。因此,插入容量 集群永远不会超过该单个分片的插入容量。
如果插入量大于单个分片可以处理的量, 如果你不能避免单调递增的分片键,那么 请考虑对应用程序进行以下修改:
- 反转分片键的二进制位。这样可以保留 信息,并避免将插入顺序与增加相关联 值序列。
- 交换第一个和最后一个 16 位单词以"随机播放"插入内容。