Мені потрібно написати велику кількість документів у 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()
операцією. Тож результати повинні бути однаковими. Якщо це не те, що ви спостерігаєте, опублікуйте нове запитання з мінімальним випадком, який відтворює те, що ви намагалися.