Best Practices für Cloud Firestore

Verwenden Sie die hier aufgeführten Best Practices als Kurzreferenz beim Erstellen einer Anwendung, die Cloud Firestore verwendet.

Speicherort der Datenbank

Wählen Sie beim Erstellen Ihrer Datenbankinstanz den Datenbankspeicherort aus, der Ihren Benutzern und Rechenressourcen am nächsten liegt. Weitreichende Netzwerksprünge sind fehleranfälliger und erhöhen die Abfragelatenz.

Um die Verfügbarkeit und Dauerhaftigkeit Ihrer Anwendung zu maximieren, wählen Sie einen Standort mit mehreren Regionen aus und platzieren Sie kritische Rechenressourcen in mindestens zwei Regionen.

Wählen Sie einen regionalen Standort aus, um die Kosten zu senken, die Schreiblatenz zu verringern, wenn Ihre Anwendung latenzempfindlich ist, oder für die gemeinsame Nutzung mit anderen GCP-Ressourcen .

Dokument-IDs

  • Vermeiden Sie die Dokument-IDs . und .. .
  • Vermeiden Sie die Verwendung von / -Schrägstrichen in Dokument-IDs.
  • Verwenden Sie keine monoton ansteigenden Dokument-IDs wie:

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

    Solche sequenziellen IDs können zu Hotspots führen, die sich auf die Latenz auswirken.

Feldnamen

  • Vermeiden Sie die folgenden Zeichen in Feldnamen, da sie zusätzliche Escapezeichen erfordern:

    • . Zeitraum
    • [ linke Klammer
    • ] rechte Klammer
    • * Sternchen
    • ` Backtick

Indizes

  • Vermeiden Sie die Verwendung zu vieler Indizes. Eine übermäßige Anzahl von Indizes kann die Schreiblatenz erhöhen und die Speicherkosten für Indexeinträge erhöhen.

  • Beachten Sie, dass das Indizieren von Feldern mit monoton ansteigenden Werten, z. B. Zeitstempeln, zu Hotspots führen kann, die sich auf die Latenz für Anwendungen mit hohen Lese- und Schreibraten auswirken.

Index-Ausnahmen

Bei den meisten Apps können Sie sich bei der Verwaltung Ihrer Indizes auf die automatische Indizierung sowie Links zu Fehlermeldungen verlassen. In den folgenden Fällen möchten Sie jedoch möglicherweise Einzelfeldausnahmen hinzufügen:

Fall Beschreibung
Große Zeichenfolgenfelder

Wenn Sie ein Zeichenfolgenfeld haben, das häufig lange Zeichenfolgenwerte enthält, die Sie nicht für Abfragen verwenden, können Sie die Speicherkosten senken, indem Sie das Feld von der Indizierung ausnehmen.

Hohe Schreibraten in eine Sammlung, die Dokumente mit sequenziellen Werten enthält

Wenn Sie ein Feld indizieren, das zwischen Dokumenten in einer Sammlung sequenziell zunimmt oder abnimmt, wie z. B. ein Zeitstempel, beträgt die maximale Schreibrate in die Sammlung 500 Schreibvorgänge pro Sekunde. Wenn Sie keine Abfrage basierend auf dem Feld mit sequenziellen Werten durchführen, können Sie das Feld von der Indizierung ausnehmen, um dieses Limit zu umgehen.

In einem IoT-Anwendungsfall mit einer hohen Schreibrate könnte beispielsweise eine Sammlung, die Dokumente mit einem Zeitstempelfeld enthält, die Grenze von 500 Schreibvorgängen pro Sekunde erreichen.

Große Array- oder Kartenfelder

Große Array- oder Zuordnungsfelder können die Grenze von 40.000 Indexeinträgen pro Dokument erreichen. Wenn Sie nicht auf der Grundlage eines großen Arrays oder Zuordnungsfelds abfragen, sollten Sie es von der Indizierung ausnehmen.

Lese- und Schreiboperationen

  • Vermeiden Sie es, mehr als einmal pro Sekunde in ein Dokument zu schreiben. Weitere Informationen finden Sie unter Aktualisierungen eines einzelnen Dokuments .

  • Verwenden Sie asynchrone Aufrufe, sofern verfügbar, anstelle von synchronen Aufrufen. Asynchrone Aufrufe minimieren die Auswirkungen der Latenz. Stellen Sie sich beispielsweise eine Anwendung vor, die das Ergebnis einer Dokumentsuche und die Ergebnisse einer Abfrage benötigt, bevor eine Antwort ausgegeben wird. Wenn die Suche und die Abfrage keine Datenabhängigkeit aufweisen, muss nicht synchron gewartet werden, bis die Suche abgeschlossen ist, bevor die Abfrage gestartet wird.

  • Verwenden Sie keine Offsets. Verwenden Sie stattdessen Cursors . Wenn Sie nur einen Offset verwenden, wird vermieden, dass die übersprungenen Dokumente an Ihre Anwendung zurückgegeben werden, diese Dokumente werden jedoch weiterhin intern abgerufen. Die übersprungenen Dokumente wirken sich auf die Latenz der Abfrage aus, und Ihrer Anwendung werden die zum Abrufen erforderlichen Lesevorgänge in Rechnung gestellt.

Wiederholungen von Transaktionen

Die Cloud Firestore SDKs und Clientbibliotheken wiederholen automatisch fehlgeschlagene Transaktionen, um vorübergehende Fehler zu beheben. Wenn Ihre Anwendung direkt über die REST- oder RPC -APIs statt über ein SDK auf Cloud Firestore zugreift, sollte Ihre Anwendung Transaktionswiederholungen implementieren, um die Zuverlässigkeit zu erhöhen.

Echtzeit-Updates

Für die beste Snapshot-Listener -Leistung sollten Sie Ihre Dokumente klein halten und die Leserate Ihrer Clients kontrollieren. Die folgenden Empfehlungen enthalten Richtlinien zur Maximierung der Leistung. Das Überschreiten dieser Empfehlungen kann zu einer erhöhten Benachrichtigungslatenz führen.

Empfehlung Einzelheiten
Reduzieren Sie die Abwanderungsrate von Snapshot-Listenern

Vermeiden Sie häufig wechselnde Listener, insbesondere wenn Ihre Datenbank unter erheblicher Schreiblast steht

Idealerweise sollte Ihre Anwendung kurz nach dem Öffnen einer Verbindung zu Cloud Firestore alle erforderlichen Snapshot-Listener einrichten. Nachdem Sie Ihre anfänglichen Snapshot-Listener eingerichtet haben, sollten Sie es vermeiden, Snapshot-Listener in derselben Verbindung schnell hinzuzufügen oder zu entfernen.

Um die Datenkonsistenz zu gewährleisten, muss Cloud Firestore jeden neuen Snapshot-Listener aus seinen Quelldaten vorbereiten und dann neue Änderungen nachholen. Abhängig von der Schreibrate Ihrer Datenbank kann dies ein teurer Vorgang sein.

Ihre Snapshot-Listener können eine erhöhte Latenz erfahren, wenn Sie häufig Snapshot-Listener zu Referenzen hinzufügen oder daraus entfernen. Im Allgemeinen schneidet ein ständig verbundener Zuhörer für die gleiche Datenmenge besser ab als das Anschließen und Trennen eines Zuhörers an diesem Ort. Für eine optimale Leistung sollten Snapshot-Listener eine Lebensdauer von 30 Sekunden oder länger haben. Wenn in Ihrer App Probleme mit der Listenerleistung auftreten, versuchen Sie, die Listenings und Delistings Ihrer App zu verfolgen, um festzustellen, ob sie möglicherweise zu häufig auftreten.

Snapshot-Listener pro Client begrenzen

100

Halten Sie die Anzahl der Snapshot-Listener pro Client unter 100.

Begrenzen Sie die Schreibrate der Sammlung

1.000 Operationen/Sekunde

Halten Sie die Rate der Schreibvorgänge für eine einzelne Sammlung unter 1.000 Vorgängen/Sekunde.

Begrenzen Sie die individuelle Client-Push-Rate

1 Dokument/Sekunde

Halten Sie die Rate der Dokumente, die die Datenbank an einen einzelnen Client sendet, unter 1 Dokument/Sekunde.

Begrenzen Sie die globale Client-Push-Rate

1.000.000 Dokumente/Sekunde

Halten Sie die Rate der Dokumente, die die Datenbank an alle Clients sendet, unter 1.000.000 Dokumenten/Sekunde.

Dies ist eine weiche Grenze. Cloud Firestore hindert Sie nicht daran, diesen Schwellenwert zu überschreiten, wirkt sich jedoch stark auf die Leistung aus.

Begrenzen Sie die Nutzlast einzelner Dokumente

10 KiB/Sekunde

Halten Sie die maximale Dokumentgröße, die von einem einzelnen Client heruntergeladen wird, unter 10 KiB/Sekunde.

Begrenzen Sie die globale Dokumentnutzlast

1 GiB/Sekunde

Halten Sie die maximale Dokumentgröße, die von allen Clients heruntergeladen wird, unter 1 GiB/Sekunde.

Begrenzen Sie die Anzahl der Felder pro Dokument

100

Ihre Dokumente sollten weniger als 100 Felder haben.

Machen Sie sich mit den Standardlimits von Cloud Firestore vertraut

Beachten Sie die Standardlimits für Cloud Firestore .

Achten Sie besonders auf das Limit von 1 Schreibvorgang pro Sekunde für Dokumente und das Limit von 1.000.000 gleichzeitigen Verbindungen pro Datenbank. Dies sind weiche Limits, die Cloud Firestore Sie nicht davon abhält, sie zu überschreiten. Das Überschreiten dieser Grenzwerte kann jedoch die Leistung beeinträchtigen, abhängig von Ihren gesamten Lese- und Schreibraten.

Cloud-Funktionen

Das Aktivieren einer Cloud-Funktion mit mehr als 2.000 Cloud Firestore-Ereignissen pro Sekunde kann die Fehlerrate vorübergehend erhöhen und die Latenz vorübergehend um mehrere Minuten erhöhen. Bevor Sie eine Funktion mit hohem Datenverkehr aktivieren, können Sie sich an den Support wenden , um Ihre Datenbank für Funktionen mit hohem Datenverkehr vorzubereiten und die erhöhte Latenz zu vermeiden.

Maßstäblich gestalten

Die folgenden Best Practices beschreiben, wie Situationen vermieden werden können, die zu Konfliktproblemen führen.

Updates für ein einzelnes Dokument

Sie sollten ein einzelnes Dokument nicht mehr als einmal pro Sekunde aktualisieren. Wenn Sie ein Dokument zu schnell aktualisieren, kommt es in Ihrer Anwendung zu Konflikten, einschließlich höherer Latenz, Zeitüberschreitungen und anderer Fehler.

Hohe Lese-, Schreib- und Löschraten für einen engen Dokumentenbereich

Vermeiden Sie hohe Lese- oder Schreibraten, um Dokumente lexikografisch zu schließen, da es sonst zu Konfliktfehlern in Ihrer Anwendung kommt. Dieses Problem wird als Hotspotting bezeichnet, und bei Ihrer Anwendung kann Hotspotting auftreten, wenn eine der folgenden Aktionen ausgeführt wird:

  • Erstellt neue Dokumente mit einer sehr hohen Rate und weist seine eigenen monoton ansteigenden IDs zu.

    Cloud Firestore weist Dokument-IDs mithilfe eines Scatter-Algorithmus zu. Hotspotting bei Schreibvorgängen sollte nicht auftreten, wenn Sie neue Dokumente mit automatischen Dokument-IDs erstellen.

  • Erstellt schnell neue Dokumente in einer Sammlung mit wenigen Dokumenten.

  • Erstellt neue Dokumente mit einem monoton ansteigenden Feld, wie z. B. einem Zeitstempel, mit einer sehr hohen Rate.

  • Löscht Dokumente in einer Sammlung mit hoher Rate.

  • Schreibt mit einer sehr hohen Rate in die Datenbank, ohne den Datenverkehr allmählich zu erhöhen.

Vermeiden Sie es, gelöschte Daten zu überspringen

Vermeiden Sie Abfragen, die kürzlich gelöschte Daten überspringen. Eine Abfrage muss möglicherweise eine große Anzahl von Indexeinträgen überspringen, wenn die frühen Abfrageergebnisse kürzlich gelöscht wurden.

Ein Beispiel für eine Workload, die möglicherweise viele gelöschte Daten überspringen muss, ist eine, die versucht, die ältesten Arbeitsaufgaben in der Warteschlange zu finden. Die Abfrage könnte wie folgt aussehen:

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()

Jedes Mal, wenn diese Abfrage ausgeführt wird, scannt sie die Indexeinträge für das created Feld in allen kürzlich gelöschten Dokumenten. Dies verlangsamt Abfragen.

Um die Leistung zu verbessern, verwenden Sie die start_at Methode, um den besten Startpunkt zu finden. Zum Beispiel:

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()

HINWEIS: Das obige Beispiel verwendet ein monoton ansteigendes Feld, das ein Antimuster für hohe Schreibraten ist.

Verkehr hochfahren

Sie sollten den Datenverkehr zu neuen Sammlungen schrittweise erhöhen oder Dokumente lexikografisch schließen, um Cloud Firestore genügend Zeit zu geben, Dokumente für den erhöhten Datenverkehr vorzubereiten. Wir empfehlen, mit maximal 500 Vorgängen pro Sekunde zu einer neuen Sammlung zu beginnen und dann den Traffic alle 5 Minuten um 50 % zu erhöhen. Sie können Ihren Schreibdatenverkehr auf ähnliche Weise erhöhen, aber denken Sie an die Cloud Firestore-Standardlimits . Achten Sie darauf, dass die Operationen relativ gleichmäßig über den Tastenbereich verteilt sind. Dies wird als „500/50/5“-Regel bezeichnet.

Datenverkehr in eine neue Sammlung migrieren

Ein schrittweises Hochfahren ist besonders wichtig, wenn Sie App-Traffic von einer Sammlung zu einer anderen migrieren. Eine einfache Möglichkeit, diese Migration zu handhaben, besteht darin, aus der alten Sammlung zu lesen und, wenn das Dokument nicht vorhanden ist, aus der neuen Sammlung zu lesen. Dies könnte jedoch zu einem plötzlichen Anstieg des Datenverkehrs führen, um Dokumente in der neuen Sammlung lexikografisch zu schließen. Cloud Firestore ist möglicherweise nicht in der Lage, die neue Sammlung effizient auf erhöhten Datenverkehr vorzubereiten, insbesondere wenn sie nur wenige Dokumente enthält.

Ein ähnliches Problem kann auftreten, wenn Sie die Dokument-IDs vieler Dokumente innerhalb derselben Sammlung ändern.

Die beste Strategie zum Migrieren von Datenverkehr zu einer neuen Sammlung hängt von Ihrem Datenmodell ab. Nachfolgend finden Sie eine Beispielstrategie, die als parallele Lesevorgänge bekannt ist. Sie müssen bestimmen, ob diese Strategie für Ihre Daten effektiv ist, und eine wichtige Überlegung sind die Kostenauswirkungen paralleler Vorgänge während der Migration.

Parallel liest

Um parallele Lesevorgänge zu implementieren, während Sie Datenverkehr zu einer neuen Sammlung migrieren, lesen Sie zuerst aus der alten Sammlung. Wenn das Dokument fehlt, dann lesen Sie aus der neuen Sammlung. Eine hohe Rate an Lesevorgängen nicht vorhandener Dokumente kann zu Hotspotting führen. Erhöhen Sie daher die Auslastung der neuen Sammlung schrittweise. Eine bessere Strategie besteht darin, das alte Dokument in die neue Sammlung zu kopieren und dann das alte Dokument zu löschen. Parallele Lesevorgänge schrittweise hochfahren, um sicherzustellen, dass Cloud Firestore den Datenverkehr zur neuen Sammlung verarbeiten kann.

Eine mögliche Strategie zum schrittweisen Hochfahren von Lese- oder Schreibvorgängen in eine neue Sammlung besteht darin, einen deterministischen Hash der Benutzer-ID zu verwenden, um einen zufälligen Prozentsatz von Benutzern auszuwählen, die versuchen, neue Dokumente zu schreiben. Stellen Sie sicher, dass das Ergebnis des Benutzer-ID-Hashes weder durch Ihre Funktion noch durch das Benutzerverhalten verzerrt wird.

Führen Sie in der Zwischenzeit einen Batch-Job aus, der alle Ihre Daten aus den alten Dokumenten in die neue Sammlung kopiert. Ihr Batch-Job sollte Schreibvorgänge in sequenzielle Dokument-IDs vermeiden, um Hotspots zu vermeiden. Wenn der Batch-Job abgeschlossen ist, können Sie nur aus der neuen Sammlung lesen.

Eine Verfeinerung dieser Strategie besteht darin, kleine Batches von Benutzern gleichzeitig zu migrieren. Fügen Sie dem Benutzerdokument ein Feld hinzu, das den Migrationsstatus dieses Benutzers verfolgt. Wählen Sie basierend auf einem Hash der Benutzer-ID einen Stapel von Benutzern aus, die migriert werden sollen. Verwenden Sie einen Batch-Job, um Dokumente für diesen Batch von Benutzern zu migrieren, und verwenden Sie parallele Lesevorgänge für Benutzer, die sich mitten in der Migration befinden.

Beachten Sie, dass Sie kein einfaches Rollback durchführen können, es sei denn, Sie führen während der Migrationsphase doppelte Schreibvorgänge sowohl für die alten als auch für die neuen Entitäten durch. Dies würde die anfallenden Cloud Firestore-Kosten erhöhen.

Unbefugten Zugriff verhindern

Verhindern Sie unbefugte Vorgänge in Ihrer Datenbank mit Cloud Firestore-Sicherheitsregeln. Durch die Verwendung von Regeln könnte beispielsweise ein Szenario vermieden werden, in dem ein böswilliger Benutzer wiederholt Ihre gesamte Datenbank herunterlädt.

Erfahren Sie mehr über die Verwendung von Cloud Firestore-Sicherheitsregeln .