MongoDB文档翻译-CRUD操作-批量写操作

来源:互联网 发布:php 协程并发执行curl 编辑:程序博客网 时间:2024/06/11 05:17

英文原文地址:https://docs.mongodb.com/v3.2/core/bulk-write-operations/。
本文章属个人翻译,作个人学习之用,如有雷同,纯属巧合。如有错误之处,欢迎指正。

批量写操作

概览

MongoDB给客户端提供了执行批量写操作的功能。批量写只影响单个集合。MongoDB允许应用决定批量写操作可接受的确认级别。

版本3.2新增。

db.collection.bulkWrite()方法提供了执行批量插入、更新、删除操作的功能。MongoDB也支出通过db.collection.insertMany()进行批量插入。

有序操作与无序操作

批量写操作可以有序,也可以无序。

对于有序操作,MongoDB串行执行操作。如果在处理其中一个写操作时出现了错误,MongoDB将不会处理剩下的操作,直接返回。见有序批量写

对于无序操作,MongoDB并行执行操作,但是这个行为没法保证。如果在其中一个写操作时出现了错误,MongoDB会继续处理剩下的写操作。见无序批量写

在一个分片的集合上执行有序操作一般要比执行无序操作更慢,因为有序操作中,每个操作必须等待前面的操作完成。

bulkWrite()默认执行有序操作。要指定无序写操作,在选项文档中设置ordered:false

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" : {   }}

批量插入到分片集合中的策略

大量的批量插入操作,包括初始数据插入或者常规的数据导入,会影响分片集群性能。对于批量插入,需要考虑以下几个策略:

预分割集合

如果分片集合是空的,这个集合只有一个初始块(chunk),留在单个分片上。MongoDB必须花时间来接收数据、创建分块,然后把分块分发给可用的各个分片。要避免这种性能损失,可用预先分割集合,见在分片集群中分块中的描述。

无序写到mongos

要改善分片集群的写操作,用把可选参数ordered设为fasle的bulkWrite()。mongos可以同时把写操作发给多个分片。对于空集合,可以先预分割集合,见在分片集群中分块中的描述。

避免单调瓶颈

如果你的分片键在插入过程中单调递增,所有插入的数据都会跑到集合的最优一个块(chunk),结果会被分配到单个分片上。因此,集群的插入容量不会超过单个分片的插入容量。

如果插入容量比单个分片能处理的更大,而且你又无法避免单调递增的分片键,可以在你的应用中考虑做以下修改:

  • 把分片键中的二进制位倒过来。这样既保留了信息,又避免了插入顺序和分片键的增加顺序相关联
  • 交换第一个和最后一个16位,把插入“随机化”

例子:

在以下C++例子中,把BSON ObjectId的前16位和后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}
0 0