OPTIONS
翻译或纠错本页面

MongoDB中的批量插入

在一些情况下,您也许需要将大量数据中插入或者摄取到MongoDB数据库中。 批量插入 拥有一些不同于与其它写操作的特殊考量。

使用 insert() 方法

当参数传递的是大量文档时, insert() 方法将会执行一个批量插入操作,并且原子性地插入每个文档。通过分摊 write concern 的开销,批量插入将会显著提高性能。

2.2 新版功能: 在版本 2.2中, mongo 脚本中的 insert() 方法已经获得了对批量插入的支持。

drivers 中,您可以对写关注进行批量配置而不一定限制于每个文档的级别。

驱动器在它们的插入操作中拥有一个 ContinueOnError 选项,因此即使某个插入操作失败了,该批量操作仍然可以继续插入剩余文档。

注解

在一个批量插入的过程中,如果出现了多个错误,客户端将只会收到最后的产生的错误。

参见

请查阅 Driver documentation导入导出MongoDB数据 以了解关于在应用中执行批量插入操作的更多细节。

分片集群上的批量插入

在未分片的集群中, ContinueOnError 是可选的配置,但是在一个 分片集合 上所有的批量操作都会在 ContinueOnError 的配置下运行,该选项上不能被禁止的。

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

预先分割集合

如果该分片集合为空,那么该集合就只有一个初始的、位于单一分片上的 数据段 。MongoDB就必须花时间来接收数据、建立分割,再将这些分割好的数据段分发到可用的分片上。为了避免性能的消耗,您可以根据 在集群中分裂数据块 中所描述的,对集合进行预分割。

插入到多个 mongos

为了并行化导入进程,您可以选择将插入操作发送到多个 mongos 实例中。首先根据 在集群中分裂数据块 中所描述的,对集合进行预分割。

减少单调节流

如果您的片键在一个插入中单调递增,这就意味中所有插入的数据都到了集合中最后一个数据段,这些数据将经常落在一个单一的分片中。因此,集群的插入容量将永远都不会超过该单一分片的插入容量。

如果您的插入量超过了一个单一分片可处理的范围,并且不能避免片键的单调递增,您可以考虑对应用进行下面的修改:

  • 颠倒片键的二进制位。这样做可以保留相关信息,并且避免了将插入顺序和序列值的增加相对应。

  • 交换前16位和后16位来 “重排” 插入。

示例

The following example, in C++, swaps the leading and trailing 16-bit word of BSON ObjectIds generated so that they are no longer monotonically increasing.

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 Key Internals (特别是 选择一个片键 )来了解更多关于选择片键的信息。

←   写操作性能 Storage  →