Firebase is back at Google I/O on May 10! Register now

Bonnes pratiques pour Cloud Firestore

Restez organisé à l'aide des collections Enregistrez et classez les contenus selon vos préférences.

Utilisez les bonnes pratiques répertoriées ici comme référence rapide lors de la création d'une application qui utilise Cloud Firestore.

Emplacement de la base de données

Lorsque vous créez votre instance de base de données, sélectionnez l' emplacement de la base de données le plus proche de vos utilisateurs et ressources de calcul. Les sauts de réseau étendus sont plus sujets aux erreurs et augmentent la latence des requêtes.

Pour optimiser la disponibilité et la durabilité de votre application, sélectionnez un emplacement multirégional et placez les ressources de calcul critiques dans au moins deux régions.

Sélectionnez un emplacement régional pour réduire les coûts, pour réduire la latence d'écriture si votre application est sensible à la latence ou pour une colocalisation avec d'autres ressources GCP .

ID de documents

  • Évitez les identifiants de documents . et .. .
  • Évitez d'utiliser / des barres obliques dans les ID de document.
  • N'utilisez pas d'ID de document à augmentation monotone, tels que :

    • Customer1 , Customer2 , Customer3 , ...
    • Product 1 , Product 2 , Product 3 , ...

    De tels identifiants séquentiels peuvent conduire à des hotspots qui ont un impact sur la latence.

Noms de champ

  • Évitez les caractères suivants dans les noms de champ car ils nécessitent un échappement supplémentaire :

    • . période
    • [ crochet gauche
    • ] crochet droit
    • * astérisque
    • ` backtick

Index

  • Évitez d'utiliser trop d'index. Un nombre excessif d'index peut augmenter la latence d'écriture et augmenter les coûts de stockage des entrées d'index.

  • Sachez que l'indexation des champs avec des valeurs croissantes de manière monotone, telles que les horodatages, peut entraîner des points chauds qui ont un impact sur la latence pour les applications avec des taux de lecture et d'écriture élevés.

Exemptions d'index

Pour la plupart des applications, vous pouvez compter sur l'indexation automatique ainsi que sur les liens de message d'erreur pour gérer vos index. Toutefois, vous souhaiterez peut-être ajouter des exemptions à champ unique dans les cas suivants :

Cas Description
Grands champs de chaîne

Si vous avez un champ de chaîne qui contient souvent des valeurs de chaîne longues que vous n'utilisez pas pour les requêtes, vous pouvez réduire les coûts de stockage en exemptant le champ de l'indexation.

Taux d'écriture élevés dans une collection contenant des documents avec des valeurs séquentielles

Si vous indexez un champ qui augmente ou diminue de manière séquentielle entre les documents d'une collection, comme un horodatage, le taux d'écriture maximal dans la collection est de 500 écritures par seconde. Si vous n'effectuez pas de requête basée sur le champ avec des valeurs séquentielles, vous pouvez exempter le champ de l'indexation pour contourner cette limite.

Dans un cas d'utilisation IoT avec un taux d'écriture élevé, par exemple, une collection contenant des documents avec un champ d'horodatage peut approcher la limite de 500 écritures par seconde.

Champs TTL

Si vous utilisez des stratégies TTL (durée de vie) , notez que le champ TTL doit être un horodatage. L'indexation sur les champs TTL est activée par défaut et peut affecter les performances à des taux de trafic plus élevés. Comme bonne pratique, ajoutez des exemptions de champ unique pour vos champs TTL.

Grands champs de tableau ou de carte

Les grands champs de tableau ou de carte peuvent approcher la limite de 40 000 entrées d'index par document. Si vous n'interrogez pas sur la base d'un grand tableau ou d'un champ de carte, vous devez l'exempter de l'indexation.

Opérations de lecture et d'écriture

  • Le taux maximum exact auquel une application peut mettre à jour un seul document dépend fortement de la charge de travail. Pour plus d'informations, voir Mises à jour d'un seul document .

  • Utilisez des appels asynchrones lorsqu'ils sont disponibles au lieu d'appels synchrones. Les appels asynchrones minimisent l'impact de la latence. Par exemple, considérez une application qui a besoin du résultat d'une recherche de document et des résultats d'une requête avant de rendre une réponse. Si la recherche et la requête n'ont pas de dépendance de données, il n'est pas nécessaire d'attendre de manière synchrone que la recherche se termine avant de lancer la requête.

  • N'utilisez pas de décalages. Utilisez plutôt des curseurs . L'utilisation d'un décalage évite uniquement de renvoyer les documents ignorés à votre application, mais ces documents sont toujours récupérés en interne. Les documents ignorés affectent la latence de la requête et votre application est facturée pour les opérations de lecture nécessaires pour les récupérer.

Nouvelles tentatives de transactions

Les SDK Cloud Firestore et les bibliothèques clientes relancent automatiquement les transactions ayant échoué pour traiter les erreurs transitoires. Si votre application accède à Cloud Firestore via les API REST ou RPC directement au lieu d'un SDK, votre application doit implémenter les nouvelles tentatives de transaction pour augmenter la fiabilité.

Mises à jour en temps réel

Pour optimiser les performances de l'écouteur d'instantanés , limitez la taille de vos documents et contrôlez le taux de lecture de vos clients. Les recommandations suivantes fournissent des directives pour optimiser les performances. Le dépassement de ces recommandations peut entraîner une augmentation de la latence des notifications.

Recommandation Détails
Réduire le taux de désabonnement des auditeurs d'instantanés

Évitez les écouteurs qui tournent fréquemment, en particulier lorsque votre base de données est soumise à une charge d'écriture importante

Idéalement, votre application doit configurer tous les écouteurs d'instantanés requis peu de temps après l'ouverture d'une connexion à Cloud Firestore. Après avoir configuré vos écouteurs d'instantané initiaux, vous devez éviter d'ajouter ou de supprimer rapidement des écouteurs d'instantané dans la même connexion.

Pour garantir la cohérence des données, Cloud Firestore doit amorcer chaque nouvel écouteur d'instantané à partir de ses données source, puis rattraper les nouvelles modifications. Selon le taux d'écriture de votre base de données, cette opération peut s'avérer coûteuse.

Vos écouteurs d'instantané peuvent subir une latence accrue si vous ajoutez ou supprimez fréquemment des écouteurs d'instantané aux références. En général, un écouteur constamment connecté fonctionne mieux que d'attacher et de détacher un écouteur à cet emplacement pour la même quantité de données. Pour de meilleures performances, les écouteurs d'instantané doivent avoir une durée de vie de 30 secondes ou plus. Si vous rencontrez des problèmes de performances d'écouteur dans votre application, essayez de suivre les écoutes et les désécoutes de votre application pour déterminer s'ils se produisent trop fréquemment.

Limiter les écouteurs d'instantanés par client

100

Maintenez le nombre d'écouteurs d'instantanés par client inférieur à 100.

Limiter le taux d'écriture de la collection

1 000 opérations/seconde

Maintenez le taux d'opérations d'écriture pour une collection individuelle à moins de 1 000 opérations/seconde.

Limiter le taux de push client individuel

1 document/seconde

Maintenez le taux de documents que la base de données envoie à un client individuel à moins de 1 document/seconde.

Limiter le taux global de push client

1 000 000 documents/seconde

Maintenez le taux de documents que la base de données envoie à tous les clients à moins de 1 000 000 de documents/seconde.

Il s'agit d'une limite souple. Cloud Firestore ne vous empêche pas de dépasser ce seuil mais cela affecte grandement les performances.

Limiter la charge utile des documents individuels

10 Kio/seconde

Maintenez la taille de document maximale téléchargée par un client individuel inférieure à 10 Kio/seconde.

Limiter la charge utile globale des documents

1 Gio/seconde

Maintenez la taille maximale des documents téléchargés sur tous les clients sous 1 Gio/seconde.

Limiter le nombre de champs par document

100

Vos documents doivent comporter moins de 100 champs.

Comprendre les limites standards de Cloud Firestore

Gardez à l'esprit les limites standard pour Cloud Firestore .

Portez une attention particulière à la limite d'une écriture par seconde pour les documents et à la limite de 1 000 000 de connexions simultanées par base de données. Ce sont des limites souples que Cloud Firestore ne vous empêche pas de dépasser. Toutefois, le dépassement de ces limites peut affecter les performances, en fonction de vos taux de lecture et d'écriture totaux.

Concevoir à grande échelle

Les meilleures pratiques suivantes décrivent comment éviter les situations qui créent des problèmes de conflit.

Mises à jour d'un seul document

Lorsque vous concevez votre application, tenez compte de la rapidité avec laquelle votre application met à jour des documents uniques. La meilleure façon de caractériser les performances de votre charge de travail consiste à effectuer des tests de charge. Le taux maximum exact auquel une application peut mettre à jour un seul document dépend fortement de la charge de travail. Les facteurs incluent le taux d'écriture, les conflits entre les requêtes et le nombre d'index affectés.

Une opération d'écriture de document met à jour le document et tous les index associés, et Cloud Firestore applique de manière synchrone l'opération d'écriture sur un quorum d'instances dupliquées. À des taux d'écriture suffisamment élevés, la base de données commencera à rencontrer des conflits, une latence plus élevée ou d'autres erreurs.

Taux de lecture, d'écriture et de suppression élevés pour une plage de documents restreinte

Évitez les taux de lecture ou d'écriture élevés pour fermer lexicographiquement les documents, sinon votre application rencontrera des erreurs de contention. Ce problème est connu sous le nom de hotspotting, et votre application peut être victime de hotspotting si elle effectue l'une des actions suivantes :

  • Crée de nouveaux documents à un rythme très élevé et alloue ses propres identifiants croissants de manière monotone.

    Cloud Firestore alloue les ID de document à l'aide d'un algorithme de dispersion. Vous ne devriez pas rencontrer de points chauds lors des écritures si vous créez de nouveaux documents à l'aide d'ID de document automatiques.

  • Crée de nouveaux documents à un rythme élevé dans une collection contenant peu de documents.

  • Crée de nouveaux documents avec un champ croissant de manière monotone, comme un horodatage, à un taux très élevé.

  • Supprime les documents d'une collection à un rythme élevé.

  • Écrit dans la base de données à un débit très élevé sans augmenter progressivement le trafic.

Évitez de sauter les données supprimées

Évitez les requêtes qui ignorent les données récemment supprimées. Une requête peut devoir ignorer un grand nombre d'entrées d'index si les premiers résultats de la requête ont été récemment supprimés.

Un exemple de charge de travail qui peut devoir ignorer un grand nombre de données supprimées est celle qui essaie de trouver les éléments de travail les plus anciens en file d'attente. La requête pourrait ressembler à :

docs = db.collection('WorkItems').order_by('created').limit(100)
delete_batch = db.batch()
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
delete_batch.commit()

Chaque fois que cette requête s'exécute, elle analyse les entrées d'index pour le champ created sur tous les documents récemment supprimés. Cela ralentit les requêtes.

Pour améliorer les performances, utilisez la méthode start_at pour trouver le meilleur endroit pour commencer. Par exemple:

completed_items = db.collection('CompletionStats').document('all stats').get()
docs = db.collection('WorkItems').start_at(
    {'created': completed_items.get('last_completed')}).order_by(
        'created').limit(100)
delete_batch = db.batch()
last_completed = None
for doc in docs.stream():
  finish_work(doc)
  delete_batch.delete(doc.reference)
  last_completed = doc.get('created')

if last_completed:
  delete_batch.update(completed_items.reference,
                      {'last_completed': last_completed})
  delete_batch.commit()

REMARQUE : L'exemple ci-dessus utilise un champ croissant de manière monotone qui est un anti-modèle pour les taux d'écriture élevés.

Accroître le trafic

Vous devez progressivement augmenter le trafic vers de nouvelles collections ou fermer lexicographiquement les documents pour donner à Cloud Firestore suffisamment de temps pour préparer les documents à un trafic accru. Nous vous recommandons de commencer avec un maximum de 500 opérations par seconde vers une nouvelle collection, puis d'augmenter le trafic de 50 % toutes les 5 minutes. Vous pouvez également augmenter votre trafic d'écriture, mais gardez à l'esprit les limites standard de Cloud Firestore . Assurez-vous que les opérations sont réparties de manière relativement uniforme sur toute la plage de touches. C'est ce qu'on appelle la règle "500/50/5".

Migrer le trafic vers une nouvelle collection

La montée en puissance progressive est particulièrement importante si vous migrez le trafic des applications d'une collection à une autre. Un moyen simple de gérer cette migration consiste à lire à partir de l'ancienne collection, et si le document n'existe pas, à lire à partir de la nouvelle collection. Cependant, cela pourrait entraîner une augmentation soudaine du trafic vers des documents lexicographiquement fermés dans la nouvelle collection. Cloud Firestore peut être incapable de préparer efficacement la nouvelle collection pour un trafic accru, en particulier lorsqu'elle contient peu de documents.

Un problème similaire peut se produire si vous modifiez les ID de document de nombreux documents au sein de la même collection.

La meilleure stratégie de migration du trafic vers une nouvelle collection dépend de votre modèle de données. Vous trouverez ci-dessous un exemple de stratégie connue sous le nom de lectures parallèles . Vous devrez déterminer si cette stratégie est efficace ou non pour vos données, et une considération importante sera l'impact financier des opérations parallèles pendant la migration.

Lectures parallèles

Pour implémenter des lectures parallèles lorsque vous migrez le trafic vers une nouvelle collection, lisez d'abord à partir de l'ancienne collection. Si le document est manquant, lisez-le à partir de la nouvelle collection. Un taux élevé de lectures de documents inexistants peut conduire à un hotspotting, alors assurez-vous d'augmenter progressivement la charge de la nouvelle collection. Une meilleure stratégie consiste à copier l'ancien document dans la nouvelle collection, puis à supprimer l'ancien document. Augmentez progressivement les lectures parallèles pour vous assurer que Cloud Firestore peut gérer le trafic vers la nouvelle collection.

Une stratégie possible pour augmenter progressivement les lectures ou les écritures dans une nouvelle collection consiste à utiliser un hachage déterministe de l'ID utilisateur pour sélectionner un pourcentage aléatoire d'utilisateurs essayant d'écrire de nouveaux documents. Assurez-vous que le résultat du hachage de l'ID utilisateur n'est pas faussé par votre fonction ou par le comportement de l'utilisateur.

Pendant ce temps, exécutez un travail par lots qui copie toutes vos données des anciens documents vers la nouvelle collection. Votre travail par lots doit éviter les écritures sur des ID de document séquentiels afin d'éviter les points chauds. Une fois le travail par lots terminé, vous ne pouvez lire qu'à partir de la nouvelle collection.

Un raffinement de cette stratégie consiste à migrer de petits lots d'utilisateurs à la fois. Ajoutez un champ au document utilisateur qui suit l'état de migration de cet utilisateur. Sélectionnez un lot d'utilisateurs à migrer en fonction d'un hachage de l'ID utilisateur. Utilisez une tâche par lots pour migrer des documents pour ce lot d'utilisateurs et utilisez des lectures parallèles pour les utilisateurs au milieu de la migration.

Notez que vous ne pouvez pas facilement revenir en arrière à moins d'effectuer une double écriture de l'ancienne et de la nouvelle entité pendant la phase de migration. Cela augmenterait les coûts Cloud Firestore encourus.

Empêcher l'accès non autorisé

Empêchez les opérations non autorisées sur votre base de données avec les règles de sécurité Cloud Firestore. Par exemple, l'utilisation de règles peut éviter un scénario dans lequel un utilisateur malveillant télécharge à plusieurs reprises l'intégralité de votre base de données.

En savoir plus sur l'utilisation des règles de sécurité Cloud Firestore .