首页 > 解决方案 > 将大量文档写入 Firestore 的最快方法是什么?

问题描述

我需要将大量文档写入 Firestore。

在 Node.js 中执行此操作的最快方法是什么?

标签: node.jsfirebasegoogle-cloud-firestore

解决方案


TL;DR:在 Firestore 上执行批量日期创建的最快方法是执行并行的单独写入操作。

将 1,000 个文档写入 Firestore 需要:

  1. ~105.4s使用顺序的单独写入操作时
  2. ~ 2.8s使用 (2) 批量写入操作时
  3. ~ 1.5s使用并行单独写入操作时

在 Firestore 上执行大量写入操作的常用方法有 3 种。

  1. 按顺序执行每个单独的写操作。
  2. 使用批量写入操作。
  3. 并行执行单个写入操作。

我们将在下面依次研究每一个,使用一组随机文档数据。


单独的顺序写操作

这是最简单的解决方案:

async function testSequentialIndividualWrites(datas) {
  while (datas.length) {
    await collection.add(datas.shift());
  }
}

我们依次编写每个文档,直到我们编写完每个文档。我们等待每个写操作完成,然后再开始下一个。

使用这种方法写入 1,000 个文档大约需要 105 秒,因此吞吐量大约是每秒 10 个文档写入


使用批量写入操作

这是最复杂的解决方案。

async function testBatchedWrites(datas) {
  let batch = admin.firestore().batch();
  let count = 0;
  while (datas.length) {
    batch.set(collection.doc(Math.random().toString(36).substring(2, 15)), datas.shift());
    if (++count >= 500 || !datas.length) {
      await batch.commit();
      batch = admin.firestore().batch();
      count = 0;
    }
  }
}

您可以看到我们BatchedWrite通过调用创建了一个对象,将batch()其填充到最大容量为 500 个文档,然后将其写入 Firestore。我们给每个文档一个生成的名字,这个名字相对可能是唯一的(对于这个测试来说已经足够好了)。

使用这种方法写入 1,000 个文档大约需要 2.8 秒,因此吞吐量约为每秒 357 个文档写入

这比顺序单独写入要快得多。事实上:许多开发人员使用这种方法是因为他们认为它是最快的,但正如上面的结果已经表明这不是真的。由于批次的大小限制,代码是迄今为止最复杂的。


并行单独的写操作

Firestore 文档说明了添加大量数据的性能

对于批量数据输入,请使用具有并行化单独写入的服务器客户端库。批量写入的性能优于序列化写入,但不优于并行写入。

我们可以使用以下代码对其进行测试:

async function testParallelIndividualWrites(datas) {
  await Promise.all(datas.map((data) => collection.add(data)));
}

此代码add尽可能快地启动操作,然后用于Promise.all()等待它们全部完成。使用这种方法,操作可以并行运行。

使用这种方法写入 1,000 个文档大约需要 1.5 秒,因此吞吐量大约为每秒 667 个文档写入

差异并不像前两种方法那么大,但它仍然比批量写入快 1.8 倍以上。


几点注意事项:

  • 你可以在Github上找到这个测试的完整代码。
  • 虽然测试是使用 Node.js 完成的,但您可能会在 Admin SDK 支持的所有平台上获得类似的结果。
  • 但是不要使用客户端 SDK 执行批量插入,因为结果可能非常不同并且更难以预测。
  • 像往常一样,实际性能取决于您的机器、互联网连接的带宽和延迟以及许多其他因素。基于这些,您也可能会看到差异中的差异,尽管我希望顺序保持不变。
  • 如果您在自己的测试中有任何异常值,或者发现完全不同的结果,请在下方发表评论。
  • 批量写入是原子的。因此,如果您的文档之间存在依赖关系,并且必须写入所有文档,或者必须不编写任何文档,则应该使用批量写入。

推荐阅读