Docs 菜单
Docs 主页
/
数据库手册
/

批量写入操作

MongoDB为客户端提供批量执行写入操作的能力。从MongoDB 8.0 开始,您可以跨多个数据库和集合执行批量写入操作。如果您使用的是MongoDB 8.0 之前的版本,则可以对单个集合批量写入操作。

要跨 MongoDB 8.0 中的多个数据库和集合执行批量写入操作,请使用 bulkWrite 数据库命令或 Mongo.bulkWrite() mongosh 方法。

要对单个集合执行批量写入操作,请使用 db.collection.bulkWrite() mongosh 方法。如果运行的是MongoDB 8.0 或更高版本,还可以使用 bulkWriteMongo.bulkWrite() 写入单个集合。

您可以将批量写入操作设立为有序无序

对于有序的操作列表, MongoDB以串行方式执行操作。如果在处理其中一个写入操作期间发生错误, MongoDB将返回而不处理列表中任何剩余的写入操作。

对于操作的无序列表, MongoDB可以并行执行操作,但不保证一定会执行此行为。如果在处理其中一个写入操作期间发生错误, MongoDB将继续进程列表中剩余的写入操作。

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

默认下,所有批量写入命令和方法都执行有序操作。要指定无序操作,请在调用首选命令或方法时将 ordered 选项设立为 false。要学习;了解有关每个命令或方法的语法的更多信息,请参阅上面链接的相应页面。

所有批量写入方法和命令都支持以下写入操作:

  • insertOne

  • updateOne

  • UpdateMany

  • replaceOne

  • deleteOne

  • deleteMany

当您调用首选命令或方法时,您将每个写入操作作为大量中的文档传递。要学习;了解有关每个命令或方法的语法的更多信息,请参阅上面链接的相应页面。

以下db.collection.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: {}
}

有关更多示例,请参阅 db。集合.bulkWrite() 示例。

此示例使用 Mongo.bulkWrite() 按顺序执行以下操作:

  • 将文档插入到 db.authors集合中

  • 将文档插入到 db.books集合中

  • 更新上一个文档

db.getMongo().bulkWrite(
[
{
namespace: 'db.authors',
name: 'insertOne',
document: { name: 'Stephen King' }
},
{
namespace: 'db.books',
name: 'insertOne',
document: { name: 'It' }
},
{
namespace: 'db.books',
name: 'updateOne',
filter: { name: 'it' },
update: { $set: { year: 1986 } }
}
],
{
ordered: true,
bypassDocumentValidation: true
}
)

mongosh 按顺序执行批量写入并返回以下文档:

{
acknowledged: true,
insertedCount: 2,
matchedCount: 1,
modifiedCount: 1,
deletedCount: 0,
upsertedCount: 0,
insertResults: { '1': { insertedId: ObjectId('67ed8ce8efd926c84cab7945') },
'2': { insertedId: ObjectId('67ed8ce8efd926c84cab7946') } }
updateResults: { '1': { matchedCount: 1, modifiedCount: 1, didUpsert: false } }
}

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

如果您的分片集合为空,且分片键的第一个键没有使用哈希分片,则您的集合只有一个初始数据块,而它位于单个分片上。然后,MongoDB 必须花费一些时间来接收数据并将数据块分发到可用的分片。为避免出现此性能费用,可通过在分片集群中创建范围来预先分割此集合。

要提高分片的片集群的写入性能,请在调用首选方法或命令时将 ordered 设置为 false,以执行无序批量写入。mongos 可以尝试同时向多个分片发送写入内容。对于集合,首先按照分片集群中的分割数据段中的描述预分割集合。

如果分片键在插入期间单调增加,则所有已插入数据都会进入集合中的最后一个数据段,该数据段将始终出现在单个分片上。因此,集群的插入容量永远不会超过该单个分片的插入容量。

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

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

  • 交换第一个和最后一个 16 位字,“随机打乱”插入。

例子

以下示例(采用 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
}

提示

分片键以了解有关选择分片键的信息。另请参阅分片键内部信息(特别是选择分片键)。

后退

方法

在此页面上