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 d'effectuer la création de dates 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, à l'aide d'un tableau de données de documents aléatoires.
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 objet BatchedWrite
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, donc le débit est d'environ 357 écritures de document par seconde .
C'est un peu plus rapide qu'avec les écritures individuelles séquentielles. 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 pour l'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 opérations add
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, donc le débit est d'environ 667 écritures de document 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: