web-dev-qa-db-fra.com

Quel est le moyen le plus rapide pour écrire un grand nombre de documents dans Firestore?

Je dois écrire un grand nombre de documents dans Firestore.

Quel est le moyen le plus rapide de le faire dans Node.js?

10
Frank van Puffelen

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:

  1. ~105.4s Lors de l'utilisation d'opérations d'écriture individuelles séquentielles
  2. ~ 2.8s Lors de l'utilisation de (2) opérations d'écriture par lots
  3. ~ 1.5s Lors de l'utilisation d'opérations d'écriture individuelles parallèles

Il existe trois façons courantes d'effectuer un grand nombre d'opérations d'écriture sur Firestore.

  1. Effectuez chaque opération d'écriture individuelle en séquence.
  2. Utilisation d'opérations d'écriture par lots.
  3. Effectuer des opérations d'écriture individuelles en parallèle.

Nous étudierons chacun d'eux tour à tour ci-dessous, à l'aide d'un tableau de données de documents aléatoires.


Opérations d'écriture séquentielles individuelles

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 .


Utilisation d'opérations d'écriture par lots

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.


Opérations d'écriture individuelles parallèles

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:

  • Vous pouvez trouver le code complet de ce test sur Github .
  • Bien que le test ait été effectué avec Node.js, vous obtiendrez probablement des résultats similaires sur toutes les plates-formes prises en charge par le SDK Admin.
  • Cependant, n'effectuez pas d'insertions en masse à l'aide des SDK clients, car les résultats peuvent être très différents et beaucoup moins prévisibles.
  • Comme d'habitude, les performances réelles dépendent de votre machine, de la bande passante et de la latence de votre connexion Internet et de nombreux autres facteurs. Sur la base de ceux-ci, vous pouvez également voir des différences dans les différences, bien que je m'attende à ce que la commande reste la même.
  • Si vous avez des valeurs aberrantes dans vos propres tests ou si vous trouvez des résultats complètement différents, laissez un commentaire ci-dessous.
  • Les écritures de lots sont atomiques. Donc, si vous avez des dépendances entre les documents et que tous les documents doivent être écrits, ou qu'aucun d'entre eux ne doit être écrit, vous devez utiliser une écriture par lots.
21
Frank van Puffelen