Je dois écrire un grand nombre de documents dans Firestore.
Quel est le moyen le plus rapide de le faire dans Node.js?
la source
Je dois écrire un grand nombre de documents dans Firestore.
Quel est le moyen le plus rapide de le faire dans Node.js?
TL; DR: Le moyen le plus rapide pour effectuer une création de date en bloc sur Firestore est d'effectuer des opérations d'écriture individuelles parallèles.
Écrire 1000 documents dans Firestore prend:
~105.4s
lors de l'utilisation d'opérations d'écriture individuelles séquentielles~ 2.8s
lors de l'utilisation de (2) opérations d'écriture par lots~ 1.5s
lors de l'utilisation d'opérations d'écriture individuelles parallèlesIl existe trois façons courantes d'effectuer un grand nombre d'opérations d'écriture sur Firestore.
Nous étudierons chacun d'eux tour à tour ci-dessous, en utilisant un tableau de données de document randomisées.
C'est la solution la plus simple possible:
async function testSequentialIndividualWrites(datas) {
while (datas.length) {
await collection.add(datas.shift());
}
}
Nous écrivons chaque document tour à tour, jusqu'à ce que nous ayons écrit chaque document. Et nous attendons la fin de chaque opération d'écriture avant de commencer la suivante.
L'écriture de 1 000 documents prend environ 105 secondes avec cette approche, donc le débit est d'environ 10 écritures de document par seconde .
Il s'agit de la solution la plus complexe.
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;
}
}
}
Vous pouvez voir que nous créons un BatchedWrite
objet en appelant batch()
, le remplissons jusqu'à sa capacité maximale de 500 documents, puis l'écrivons dans Firestore. Nous donnons à chaque document un nom généré qui est relativement susceptible d'être unique (assez bon pour ce test).
L'écriture de 1 000 documents prend environ 2,8 secondes avec cette approche, le débit est donc d'environ 357 documents écrits par seconde .
C'est un peu plus rapide qu'avec les écritures séquentielles individuelles. En fait: de nombreux développeurs utilisent cette approche car ils supposent qu'elle est la plus rapide, mais comme les résultats ci-dessus l'ont déjà montré, ce n'est pas vrai. Et le code est de loin le plus complexe, en raison de la contrainte de taille sur les lots.
La documentation Firestore en dit long sur les performances d'ajout de nombreuses données :
Pour la saisie de données en masse, utilisez une bibliothèque cliente de serveur avec des écritures individuelles parallélisées. Les écritures par lots fonctionnent mieux que les écritures sérialisées mais pas mieux que les écritures parallèles.
Nous pouvons mettre cela à l'épreuve avec ce code:
async function testParallelIndividualWrites(datas) {
await Promise.all(datas.map((data) => collection.add(data)));
}
Ce code lance les add
opérations aussi vite que possible, puis utilise Promise.all()
pour attendre qu'elles soient toutes terminées. Avec cette approche, les opérations peuvent s'exécuter en parallèle.
L'écriture de 1 000 documents prend environ 1,5 seconde avec cette approche, le débit est donc d'environ 667 documents écrits par seconde .
La différence n'est pas aussi grande qu'entre les deux premières approches, mais elle est toujours 1,8 fois plus rapide que les écritures par lots.
Quelques notes:
add()
ne fait rien de plus que de générer un ID unique (purement côté client), suivi d'uneset()
opération. Les résultats devraient donc être les mêmes. Si ce n'est pas ce que vous observez, postez une nouvelle question avec l'étui minimal qui reproduit ce que vous avez essayé.