概述

MongoDB使客户端能够批量执行写操作。批量写入操作会影响单个集合。MongoDB允许应用程序确定批量写入操作所需的可接受的确认级别。

3.2版中的新功能。

db.collection.bulkWrite()方法提供了执行批量插入,更新和删除操作的能力。MongoDB还支持通过db.collection.insertMany()批量插入。

有序与无序操作 批量写操作可以有序或无序。

通过操作的有序列表,MongoDB串行执行操作。如果在写操作之一的处理过程中发生错误,MongoDB将返回而不处理列表中任何剩余的写操作。请参阅有序的批量写入

使用无序的操作列表,MongoDB可以并行执行操作,但是不能保证此行为。如果在写操作之一的处理过程中发生错误,MongoDB将继续处理列表中剩余的写操作。请参阅无序批量写入。

在分片集合上执行操作的有序列表通常比执行无序列表要慢,因为对于有序列表,每个操作必须等待上一个操作完成。

默认情况下,bulkWrite()执行ordered 操作。要指定unordered写操作,请在选项文档中进行设置 。ordered : false

请参阅执行操作

bulkWrite()方法 bulkWrite() 支持以下写操作:

insertOne updateOne updateMany replaceOne deleteOne deleteMany 每个写操作都bulkWrite()作为文档传递到数组中。

例如,以下执行多个写操作:

该characters集合包含以下文档:

{ “ _id” : 1 , “ char” : “布里斯班” , “ class” : “和尚” , “ lvl” : 4 }, { “ _id” : 2 , “ char” : “ Eldon” , “ class” : “ alchemist” , “ lvl” : 3 }, { “ _id” : 3 , “ char” : “ Meldane” , “ class” : “ ranger”, “ lvl” : 3 } 以下bulkWrite()对集合执行多项操作:

尝试 { db 。字符。bulkWrite ( [ { insertOne : { “ document” : { “ _id” : 4 , “ char” : “ Dithras” , “ class” : “ barbarian” , “ lvl” : 4 } } } } } {{ insertOne : { “ document” : { “ _id” : 5 , “ char” : “ Taeln” , “ , “ lvl” : 3 } } }, { updateOne : { “ filter” : { “ char” : “ Eldon” }, “ update” : { $ set : { “ status” : “严重伤害” } } } }, { 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()示例

批量插入分片集合的策略 大量的大容量插入操作(包括初始数据插入或常规数据导入)可能会影响分片群集的性能。对于批量插入,请考虑以下策略:

预分割集合 如果分片集合为空,则该集合只有一个初始块,该块位于单个分片上。然后,MongoDB必须花一些时间来接收数据,创建拆分并将拆分的块分发到可用的分片。为了避免这种性能损失,您可以按照拆分碎片中的拆分块中的说明预先拆分集合 。

无序写入mongos 要提高对分片群集的写入性能,请使用 bulkWrite()可选参数ordered 设置为false。mongos可以尝试同时将写入发送到多个分片。对于空集合,首先按照分片群集中的分割块中的说明预先分割集合 。

避免单调节流 如果您的分片键在插入过程中单调增加,则所有插入的数据将到达集合中的最后一块,该块将始终以单个分片结尾。因此,群集的插入容量将永远不会超过该单个分片的插入容量。

如果插入量大于单个分片可以处理的插入量,并且如果无法避免单调增加的分片键,请考虑对应用程序进行以下修改:

反转分片密钥的二进制位。这样可以保留信息,并避免将插入顺序与值序列的增加关联起来。 交换第一个和最后一个16位字以“随机”插入。 例

在C ++中,以下示例交换 生成的BSON ObjectId的前导和尾随16位字,因此它们不再单调递增。

使用 名称空间 mongo ; OID make_an_id () { OID x = OID :: gen (); const unsigned char * p = x 。getData (); 交换( (unsigned short &) p [ 0 ], (unsigned short &) p [ 10 ] ); 返回 x ; }

void foo () { //创建一个对象 BSONObj o = BSON ( “ _id” « make_an_id () « “ x” « 3 « “ name” « “ jane” ); //现在我们可以将o插入分片集合 }