批量写入操作


进入MongoDB中文手册(4.2版本)目录

1 概述

MongoDB提供能够执行批量写操作的客户端。批量写入操作会影响单个集合。MongoDB允许应用程序确定可接受的批量写入操作所需的确认级别。
批量写入为3.2版中的新功能。
db.collection.bulkWrite()方法提供了批量插入,更新和删除操作的能力。MongoDB还支持通过db.collection.insertMany()完成批量插入。

2 有序与无序操作

批量写操作可以有序或无序。
MongoDB根据操作的有序列表串行执行操作。如果在其中一个写操作的处理过程中发生错误,MongoDB将返回,并且不处理列表中任何剩余的写操作。请参阅有序批量写入
MongoDB可以使用无序的操作列表并行执行操作,但是不能保证此行为。如果其中一个写操作的处理过程中发生错误,MongoDB将继续处理列表中剩余的写操作。请参阅无序批量写入
在分片集合上执行有序列表的操作通常比执行无序列表的操作要慢,因为对于有序列表,每个操作必须等待上一个操作完成。
默认情况下,bulkWrite()执行有序操作。要指定无序写操作,请在选项文档中进行设置 ordered : false。请参阅执行操作

3 bulkWrite()方法

bulkWrite() 支持以下写操作:

  • insertOne;
  • updateOne;
  • updateMany;
  • replaceOne;
  • deleteOne;
  • deleteMany。

每个写操作都作为文档放入数组中并传递给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()示例

4 批量插入分片集合的策略

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

4.1 预拆分集合

如果分片集合为空,则该集合只有一个初始块(chunk),它位于单个分片上。然后,MongoDB必须花一些时间来接收数据,拆分数据,并将拆分的块分发到可用的分片。为了避免这种性能损失,您可以预先拆分集合,请按照在分片集群中拆分块(Split Chunks in a Sharded Cluster)的说明 。

4.2 无序写入mongos

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

4.3 避免单调节流(Monotonic Throttling)

如果您的分片键(shard key )在插入过程中是单调地(monotonically )增加的,则所有插入的数据将存储在集合中的最后一个块(chunk)中,该块始终位于单个分片上。因此,群集的插入容量将永远不会超过该单个分片的插入容量。
如果您的插入容量大于单个分片可以处理的插入容量,并且如果您无法避免单独地增加分片键,那么请考虑对应用程序进行以下修改:

  • 反转分片密钥的二进制位。这样可以保留信息,并避免将插入顺序与增加的值序列关联起来;
  • 交换第一个和最后一个16位字,从而将插入操作“洗牌(shuffle)”。

例如,在C ++中,以下示例交换生成的BSON ObjectId的第一个和末尾的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
}

也可以看看:
分片键(Shard Keys )中获取有关选择分片键的信息。另请参见分片键内部(Shard Key Internals)(特别是 选择分片键(Choosing a Shard Key))。

进入MongoDB中文手册(4.2版本)目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值