批量写入操作

在本页面

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设置为falsemongos可以尝试同时将写入发送到多个分片。对于* 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有关选择分片密钥的信息。另请参见碎片键内部(尤其是选择分片键)。