文档菜单
文档首页
/
MongoDB 手册
/

批量写入操作

本页内容

  • 概述
  • 有序操作与无序操作
  • bulkWrite() 方法
  • 示例
  • 将批量插入到分片集合的策略

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

方法db.collection.bulkWrite() 允许执行批量插入、更新和删除操作。

MongoDB 还通过 db.collection.insertMany() 方法支持批量插入。

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

在有序操作列表中,MongoDB会串行执行操作。如果在处理某个写操作时发生错误,MongoDB将返回而不处理列表中剩余的任何写操作。请参阅有序批量写

在无序操作列表中,MongoDB可以并行执行操作,但这种行为没有保证。如果在处理某个写操作时发生错误,MongoDB将继续处理列表中剩余的写操作。请参阅无序批量写示例。

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

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

请参阅操作执行

bulkWrite()支持以下写操作

每个写操作作为数组中的文档传递给bulkWrite()

本节中的示例使用 pizzas 集合

db.pizzas.insertMany( [
{ _id: 0, type: "pepperoni", size: "small", price: 4 },
{ _id: 1, type: "cheese", size: "medium", price: 7 },
{ _id: 2, type: "vegan", size: "large", price: 8 }
] )

以下 bulkWrite() 示例在 pizzas 集合上运行这些操作

  • 使用 insertOne 添加两个文档。

  • 使用 updateOne 更新一个文档。

  • 使用 deleteOne 删除一个文档。

  • 使用 replaceOne 替换一个文档。

try {
db.pizzas.bulkWrite( [
{ insertOne: { document: { _id: 3, type: "beef", size: "medium", price: 6 } } },
{ insertOne: { document: { _id: 4, type: "sausage", size: "large", price: 10 } } },
{ updateOne: {
filter: { type: "cheese" },
update: { $set: { price: 8 } }
} },
{ deleteOne: { filter: { type: "pepperoni"} } },
{ replaceOne: {
filter: { type: "vegan" },
replacement: { type: "tofu", size: "small", price: 4 }
} }
] )
} catch( error ) {
print( error )
}

示例输出,包括已完成的操作摘要

{
acknowledged: true,
insertedCount: 2,
insertedIds: { '0': 3, '1': 4 },
matchedCount: 2,
modifiedCount: 2,
deletedCount: 1,
upsertedCount: 0,
upsertedIds: {}
}

有关更多示例,请参阅 bulkWrite() 示例。

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

如果分片集合为空,则该集合只有一个初始的 数据块,它位于单个分片上。然后MongoDB必须花费时间接收数据、创建分割并分配分割数据块到可用的分片。为了避免这种性能开销,您可以根据《在分片集群中分割数据块》的描述预先分割集合。

为了提高写入分片集群的性能,请使用带有可选参数 ordered 设置为 falsebulkWrite()mongos 可以尝试同时将写入发送到多个分片。对于 集合,首先按照《在分片集群中分割数据块》中的描述预先分割集合。

如果在插入过程中分片键单调递增,则所有插入的数据都将进入集合的最后一个数据块,该数据块始终位于单个分片上。因此,集群的插入容量永远不会超过单个分片的插入容量。

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

  • 反转分片键的二进制位。这保留了信息,避免了将插入顺序与值的递增序列相关联。

  • 交换前16位和最后16位字以“洗牌”插入。

示例

以下示例,在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
}

提示

另请参阅

分片键 了解选择分片键的信息。另请参阅 分片键内部机制(特别是,选择分片键)。

返回

方法