Мне нужно написать большое количество документов в Firestore.
Какой самый быстрый способ сделать это в Node.js?
Мне нужно написать большое количество документов в Firestore.
Какой самый быстрый способ сделать это в Node.js?
Ответы:
TL; DR. Самый быстрый способ выполнить массовое создание даты в Firestore - это выполнить параллельные отдельные операции записи.
Запись 1000 документов в Firestore занимает:
~105.4s
при использовании последовательных отдельных операций записи~ 2.8s
при использовании (2) операций пакетной записи~ 1.5s
при использовании параллельных отдельных операций записиСуществует три распространенных способа выполнения большого количества операций записи в Firestore.
Мы рассмотрим каждый из них по очереди, используя массив случайных данных документа.
Это самое простое из возможных решений:
async function testSequentialIndividualWrites(datas) {
while (datas.length) {
await collection.add(datas.shift());
}
}
Мы пишем каждый документ по очереди, пока не напишем каждый документ. И мы ждем завершения каждой операции записи, прежде чем начинать следующую.
При таком подходе запись 1000 документов занимает около 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. Мы даем каждому документу сгенерированное имя, которое, скорее всего, будет уникальным (достаточно для этого теста).
При таком подходе запись 1000 документов занимает около 2,8 секунды, поэтому пропускная способность составляет примерно 357 операций записи документов в секунду .
Это немного быстрее, чем с последовательными отдельными записями. На самом деле: многие разработчики используют этот подход, потому что считают, что он самый быстрый, но, как уже показали результаты, это не так. И код на сегодняшний день является наиболее сложным из-за ограничения размера пакетов.
Документация Firestore говорит о производительности для добавления большого количества данных :
Для массового ввода данных используйте серверную клиентскую библиотеку с распараллеленными отдельными записями. Пакетные записи работают лучше, чем сериализованные записи, но не лучше, чем параллельные записи.
Мы можем проверить это с помощью этого кода:
async function testParallelIndividualWrites(datas) {
await Promise.all(datas.map((data) => collection.add(data)));
}
Этот код запускает add
операции так быстро, как может, а затем использует, Promise.all()
чтобы дождаться их завершения. При таком подходе операции могут выполняться параллельно.
При таком подходе запись 1000 документов занимает около 1,5 секунд, поэтому пропускная способность составляет примерно 667 операций записи документов в секунду .
Разница не так велика, как между первыми двумя подходами, но все же в 1,8 раза быстрее, чем пакетная запись.
Несколько заметок:
add()
не делает ничего, кроме генерации уникального идентификатора (чисто на стороне клиента), за которым следует set()
операция. Так что результаты должны быть одинаковыми. Если это не то, что вы наблюдаете, опубликуйте новый вопрос с минимальным регистром, который воспроизводит то, что вы пробовали.