Overview
MongoDB为客户端提供批量执行写入操作的能力。从MongoDB 8.0 开始,您可以跨多个数据库和集合执行批量写入操作。如果您使用的是MongoDB 8.0 之前的版本,则可以对单个集合批量写入操作。
要跨 MongoDB 8.0 中的多个数据库和集合执行批量写入操作,请使用 bulkWrite 数据库命令或 Mongo.bulkWrite() mongosh 方法。
要对单个集合执行批量写入操作,请使用 db.collection.bulkWrite() mongosh 方法。如果运行的是MongoDB 8.0 或更高版本,还可以使用 bulkWrite 或 Mongo.bulkWrite() 写入单个集合。
有序操作与无序操作
批量写入操作可以串行(有序)或按任意顺序(无序)执行。默认下,操作是有序的,并在出现第一个错误时停止。尽管出现错误,无序操作仍会继续,并且可以并行执行,这对于分片的集合来说通常速度更快。
有关执行行为和错误处理的详细信息,请参阅db.collection.bulkWrite() 或Mongo.bulkWrite() 。
支持的操作
批量写入操作支持:插入一个、更新一个、更新多个、替换一个、删除一个和删除多个。
批量插入分片集合的策略
大批量插入操作可能会影响分片集群性能。要优化对分片的集合的批量写入,请执行以下操作:
预拆分集合
如果您的分片集合为空,且分片键的第一个键没有使用哈希分片,则您的集合只有一个初始数据块,而它位于单个分片上。然后,MongoDB 必须花费一些时间来接收数据并将数据块分发到可用的分片。为避免出现此性能费用,可通过在分片集群中创建范围来预先分割此集合。
无序写入到 mongos
要提高分片的片集群的写入性能,请在执行批量写入时通过将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 }