On this page
批量写入操作
在本页面
Overview
MongoDB 使 Client 端能够批量执行写操作。批量写入操作会影响单个集合。 MongoDB 允许应用程序确定批量写入操作所需的可接受的确认级别。
3.2 版中的新功能。
db.collection.bulkWrite()方法提供了执行批量插入,更新和删除操作的能力。 MongoDB 还支持通过db.collection.insertMany()进行批量插入。
有序与无序操作
批量写入操作可以有序或无序。
通过操作的有序列表,MongoDB 串行执行操作。如果在写操作之一的处理过程中发生错误,MongoDB 将返回而不处理列表中任何剩余的写操作。见有序批量写入
使用无序的操作列表,MongoDB 可以并行执行操作,但是不能保证此行为。如果在写操作之一的处理过程中发生错误,MongoDB 将 continue 处理列表中剩余的写操作。参见无序批量写入。
在分片集合上执行操作的有序列表通常比执行无序列表要慢,因为对于有序列表,每个操作必须 await 上一个操作完成。
默认情况下,bulkWrite()执行ordered
个操作。要指定unordered
写操作,请在选项文档中设置ordered : false
。
See 执行作业
bulkWrite() Methods
bulkWrite()支持以下写操作:
每个写操作都作为数组中的文档传递给bulkWrite()。
例如,以下执行多个写操作:
characters
集合包含以下文档:
{ "_id" : 1, "char" : "Brisbane", "class" : "monk", "lvl" : 4 },
{ "_id" : 2, "char" : "Eldon", "class" : "alchemist", "lvl" : 3 },
{ "_id" : 3, "char" : "Meldane", "class" : "ranger", "lvl" : 3 }
以下bulkWrite()对集合执行多项操作:
try {
db.characters.bulkWrite(
[
{ insertOne :
{
"document" :
{
"_id" : 4, "char" : "Dithras", "class" : "barbarian", "lvl" : 4
}
}
},
{ insertOne :
{
"document" :
{
"_id" : 5, "char" : "Taeln", "class" : "fighter", "lvl" : 3
}
}
},
{ updateOne :
{
"filter" : { "char" : "Eldon" },
"update" : { $set : { "status" : "Critical Injury" } }
}
},
{ deleteOne :
{ "filter" : { "char" : "Brisbane"} }
},
{ replaceOne :
{
"filter" : { "char" : "Meldane" },
"replacement" : { "char" : "Tanys", "class" : "oracle", "lvl" : 4 }
}
}
]
);
}
catch (e) {
print(e);
}
该操作返回以下内容:
{
"acknowledged" : true,
"deletedCount" : 1,
"insertedCount" : 2,
"matchedCount" : 2,
"upsertedCount" : 0,
"insertedIds" : {
"0" : 4,
"1" : 5
},
"upsertedIds" : {
}
}
有关更多示例,请参见bulkWrite() Examples
批量插入分片集合的策略
大量的插入操作(包括初始数据插入或常规数据导入)可能会影响sharded cluster的性能。对于批量插入,请考虑以下策略:
预拆分收藏集
如果分片集合为空,则该集合只有一个初始chunk,它位于单个分片上。然后,MongoDB 必须花一些时间来接收数据,创建拆分并将拆分的块分发到可用的分片。为避免这种性能损失,您可以按照分片群集中的分割块中的说明预先拆分集合。
无序写入 mongos
要提高对分片群集的写入性能,请使用bulkWrite()并将可选参数ordered
设置为false
。 mongos可以尝试同时将写入发送到多个分片。对于* empty *集合,首先按照分片群集中的分割块中的说明预分割集合。
避免单调节流
如果您的分片键在插入期间单调增加,则所有插入的数据都将到达集合中的最后一块,该块将始终以单个分片结尾。因此,群集的插入容量将永远不会超过该单个分片的插入容量。
如果插入量大于单个分片可以处理的插入量,并且如果无法避免单调增加的分片键,请考虑对应用程序进行以下修改:
反转分片密钥的二进制位。这样可以保留信息,并避免将插入 Sequences 与值序列的增加关联起来。
交换第一个和最后一个 16 位字以“随机”插入。
Example
下面的示例在 C 中交换生成的BSON ObjectIds的前导和尾随 16 位字,因此它们不再单调递增。
using namespace mongo;
OID make_an_id() {
OID x = OID::gen();
const unsigned char *p = x.getData();
swap( (unsigned short&) p[0], (unsigned short&) p[10] );
return x;
}
void foo() {
// create an object
BSONObj o = BSON( "_id" << make_an_id() << "x" << 3 << "name" << "jane" );
// now we may insert o into a sharded collection
}
See also
Shard Keys有关选择分片密钥的信息。另请参见碎片键内部(尤其是选择分片键)。