批量写入操作
在本页面
MongoDB使客户端能够批量执行写操作。 批量写入操作会影响单个集合。 MongoDB允许应用程序确定批量写入操作所需的可接受的确认级别。
3.2版本新增
批量写操作可以是有序的,也可以无序的。
在分片集合上执行有序的批量写操作通常比执行无序批量写操作要慢。这是因为对于有序列表而言,每个操作都必须等待上一个操作完成后才能执行。
例如,下面执行多个写操作:
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 }
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" : {
}
}
大容量插入操作(包括初始数据插入或例程数据导入)可能会影响分片集群的性能。对于批量插入,考虑以下策略:
如果分片集合为空,则该集合只有一个存储在单个分片上的初始数据块,MongoDB必须花一些时间来接收数据,创建拆分并将拆分的块分发到其他分片上。为了避免这种性能开销,您可以对分片集合进行预拆分,请参考 分片集群中的数据块拆分中的描述。
要提高对分片集群的写入性能,请使用带有可选参数
ordered:false
的bulkWrite()
方法。mongos
会尝试同时将写入发送到多个分片。对于空集合,请首先按照分片集群中的数据块拆分中描述的进行集合的预拆分。如果您的分片键再插入过程中时单调增加的,那么所有插入的数据都会插入到该分片集合的最后一个数据块中,也就是说会落到某单个分片上。因此,集群的插入能力将永远不会超过该单个跟片的插入性能(木桶的短板原理)。
如果插入量大于单个分片可以处理的数据量,并且无法避免单调增加的分片键,那么可以考虑对应用程序进行如下修改:
- 翻转分片键的二进制位。这样可以保留信息的同时避免插入顺序与递增插入值之间的关联性。
- 交换第一个和最后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
}
另请参考
译者:杨帅 刘翔
校验:杨帅
最近更新 1yr ago