Indexe optimieren

Auf dieser Seite werden Konzepte beschrieben, die bei der Auswahl von Firestore-Indexen im Datastore-Modus für Ihre Anwendung zu berücksichtigen sind.

Firestore im Datastore-Modus bietet dadurch, dass für alle Abfragen Indexe verwendet werden, eine hohe Abfrageleistung. Die Leistung für die meisten Abfragen hängt von der Größe der Ergebnismenge und nicht von der Gesamtgröße der Datenbank ab.

Firestore im Datastore-Modus definiert integrierte Indexe für jedes Attribut in einer Entität. Diese Indexe mit einzelnen Attributen unterstützen eine große Anzahl einfacher Abfragen. Firestore im Datastore-Modus arbeitet mit einer Indexzusammenführungsfunktion, mit der integrierte Indexe in Ihrer Datenbank zusammengeführt werden können. Hierdurch werden zusätzliche Abfragen möglich. Bei komplexeren Abfragen müssen Sie zusammengesetzte Indexe im Voraus definieren.

Auf dieser Seite geht es um die Indexzusammenführungsfunktion, da sie zwei wichtige Möglichkeiten zur Indexoptimierung mit sich bringt:

  • Beschleunigen von Abfragen
  • Reduzieren der Anzahl zusammengesetzter Indexe

Das folgende Beispiel zeigt das praktische Funktionieren der Indexzusammenführungsfunktion.

Photo-Entitäten filtern

Betrachten Sie eine Datenbank im Datastore-Modus mit Entitäten der Art Photo:

Foto
Attribut Werttyp Beschreibung
owner_id String Nutzer-ID
tag Stringarray Tokenisierte Keywords
size Ganzzahl Enumeration:
  • 1 icon
  • 2 medium
  • 3 large
coloration Ganzzahl Enumeration:
  • 1 black & white
  • 2 color

Angenommen, Sie benötigen eine Anwendungsfunktion, mit dem Nutzer Photo-Entitäten anhand eines logischen AND der folgenden Elemente abfragen können:

  • Verfügbar sind bis zu drei Filter entsprechend den Attributen:

    • owner_id
    • size
    • coloration
  • Sie verwenden einen tag-Suchstring. Die Anwendung tokenisiert den Suchstring in Tags und fügt für jedes Tag einen Filter hinzu.

    Die Anwendung wandelt beispielsweise den Suchstring outside, family in die Abfragefilter tag=outside und tag=family um.

Mithilfe der integrierten Indexe und der Indexzusammenführungsfunktion von Firestore im Datastore-Modus können Sie die Indexanforderungen dieser Photo-Filterfunktion erfüllen, ohne zusätzliche zusammengesetzte Indexe hinzufügen zu müssen.

Die integrierten Indexe für Photo-Entitäten unterstützen Abfragen mit einzelnem Filter wie z. B.:

Python

query_owner_id = client.query(
        kind='Photo',
        filters=[('owner_id', '=', 'user1234')])

    query_size = client.query(
        kind='Photo',
        filters=[('size', '=', 2)])

    query_coloration = client.query(
        kind='Photo',
        filters=[('coloration', '=', 2)])

Die Photo-Filterfunktion erfordert auch Abfragen, die mehrere Gleichheitsfilter mit einem logischen AND kombinieren:

Python

query_all_properties = client.query(
        kind='Photo',
        filters=[('owner_id', '=', 'user1234'),
                 ('size', '=', 2),
                 ('coloration', '=', 2),
                 ('tag', '=', 'family')])

Der Firestore in Datastore-Modus kann diese Abfragen unterstützen, indem er integrierte Indizes zusammenführt.

Indexzusammenführung

Firestore im Datastore-Modus kann die Indexzusammenführung verwenden, wenn Ihre Abfrage und Ihre Indexe alle der folgenden Einschränkungen erfüllen:

  • Die Abfrage verwendet nur Gleichheitsfilter (=)
  • Es gibt keinen zusammengesetzten Index, der perfekt mit den Filtern und der Sortierung der Abfrage übereinstimmt
  • Jeder Gleichheitsfilter führt mindestens einen vorhandenen Index mit derselben Sortierung wie die Abfrage zusammen

In diesem Fall kann Firestore im Datastore-Modus mit vorhandenen Indexen die Abfrage unterstützen, anstatt einen zusätzlichen zusammengesetzten Index konfigurieren zu müssen.

Wenn zwei oder mehr Indexe nach denselben Kriterien sortiert sind, kann Firestore im Datastore-Modus die Ergebnisse mehrerer Indexscans zusammenführen, um die Ergebnisse zu finden, die allen solchen Indexen gemeinsam sind. Firestore im Datastore-Modus kann integrierte Indexe zusammenführen, da alle Werte nach Entitätsschlüssel sortiert werden.

Durch das Zusammenführen integrierter Indexe unterstützt Firestore im Datastore-Modus Abfragen mit Gleichheitsfiltern für mehrere Attribute:

Python

query_all_properties = client.query(
        kind='Photo',
        filters=[('owner_id', '=', 'user1234'),
                 ('size', '=', 2),
                 ('coloration', '=', 2),
                 ('tag', '=', 'family')])

Firestore im Datastore-Modus kann auch Indexergebnisse aus mehreren Bereichen desselben Indexes zusammenführen. Durch Zusammenführen verschiedener Bereiche des integrierten Index für das tag-Attribut unterstützt Firestore im Datastore-Modus Abfragen, bei denen mehrere tag-Filter in einem logischen AND kombiniert werden:

Python

query_tag = client.query(
        kind='Photo',
        filters=[('tag', '=', 'family'),
                 ('tag', '=', 'outside'),
                 ('tag', '=', 'camping')])

    query_owner_size_color_tags = client.query(
        kind='Photo',
        filters=[('owner_id', '=', 'user1234'),
                 ('size', '=', 2),
                 ('coloration', '=', 2),
                 ('tag', '=', 'family'),
                 ('tag', '=', 'outside'),
                 ('tag', '=', 'camping')])

Die Abfragen, die von zusammengeführten integrierten Indexen unterstützt werden, vervollständigen die für die Filterfunktion Photo erforderlichen Abfragen. Beachten Sie, dass für die Unterstützung der Filterfunktion Photo keine zusätzlichen zusammengesetzten Indexe erforderlich sind.

Bei der Auswahl der optimalen Indexe für Ihre Anwendung ist es wichtig, die Indexzusammenführungsfunktion zu verstehen. Durch das Zusammenführen von Indexen ist Firestore im Datastore-Modus flexibler bei Abfragen, die Leistung kann aber möglicherweise beeinträchtigt sein. Im nächsten Abschnitt wird die Leistung bei der Indexzusammenführung und die Leistungsverbesserung durch Hinzufügen zusammengesetzter Indexe beschrieben.

Indexauswahl optimieren

In diesem Abschnitt werden die Leistungsmerkmale der Indexzusammenführung und zwei Optimierungsmöglichkeiten im Zusammenhang mit der Indexzusammenführung beschrieben:

  • Fügen Sie zusammengesetzte Indexe hinzu, um Abfragen zu beschleunigen, die auf zusammengeführten Indexen basieren
  • Reduzieren Sie die Anzahl der zusammengesetzten Indexe, indem Sie zusammengeführte Indexe nutzen

Leistung bei Indexzusammenführung

Bei einer Indexzusammenführung erreicht Firestore im Datastore-Modus zusätzliche Effizienz mit einem Zig-Zag-Merge-Join-Algorithmus. Mithilfe dieses Algorithmus verbindet der Datastore-Modus potenzielle Übereinstimmungen aus mehreren Indexscans, um eine Ergebnismenge passend zu einer Abfrage zu erzeugen. Ein weiteres Merkmal der Indexzusammenführung ist, dass Filterkomponenten zur Lesezeit anstatt zur Schreibzeit kombiniert werden. Deshalb hängt die Leistung – im Gegensatz zu den meisten Firestore-Abfragen im Datastore-Modus, bei denen die Leistung nur von der Größe der Ergebnismenge bestimmt wird – bei Abfragen mit Indexzusammenführung von den Filtern in der Abfrage und von der Anzahl der berücksichtigten potenziellen Übereinstimmungen ab.

Die Leistung einer Indexzusammenführung ist am besten, wenn jede potenzielle Übereinstimmung in einem Index die Abfragefilter erfüllt. In diesem Fall beträgt die Leistung O(R * I), wobei R die Größe der Ergebnismenge und I die Anzahl der gescannten Indexe ist.

Die Leistung ist am geringsten, wenn die Datenbank viele potenzielle Übereinstimmungen berücksichtigen muss, aber nur wenige davon die Abfragefilter erfüllen. In diesem Fall beträgt die Leistung O(S), wobei S die Größe des kleinsten Satzes potenzieller Entitäten aus einem einzelnen Indexscan ist.

Die tatsächliche Leistung hängt von der Form der Daten ab. Die durchschnittliche Anzahl der Entitäten, die für jedes zurückgegebene Ergebnis berücksichtigt werden, beträgt O(S/(R * I)). Die Abfragequalität verschlechtert sich, wenn viele Entitäten mit jedem Indexscan übereinstimmen, aber nur wenige Entitäten mit der Abfrage als Ganzes übereinstimmen, d. h. wenn R klein und S groß ist.

Sie können jedoch das Risiko wie folgt minimieren:

  • Der Abfrageplaner sucht eine Entität erst, wenn die Entität mit der gesamten Abfrage übereinstimmt.

  • Der Zig-Zag-Algorithmus muss nicht alle Ergebnisse finden, um das jeweils nächste Ergebnis zurückzugeben. Wenn Sie die ersten zehn Ergebnisse anfordern, bezahlen Sie nur für die Latenz, um diese zehn Ergebnisse zu finden.

  • Der Zig-Zag-Algorithmus überspringt große Teile falsch positiver Ergebnisse. Die Leistung ist nur gering, wenn falsch positive Ergebnisse zwischen den Scans in der Sortierreihenfolge komplett verflochten sind.

  • Die Latenz hängt von der Anzahl der Entitäten ab, die in den einzelnen Indexscans gefunden werden, und nicht von der Anzahl der Entitäten, die mit dem jeweiligen Filter übereinstimmen. Wie im nächsten Abschnitt gezeigt, können Sie zusammengesetzte Indexe hinzufügen, um die Leistung der Indexzusammenführung zu verbessern.

Abfrage für Indexzusammenführung beschleunigen

Wenn Firestore im Datastore-Modus Indexe zusammenführt, wird jeder Indexscan häufig einem einzelnen Filter in der Abfrage zugeordnet. Sie können die Abfrageleistung verbessern, indem Sie zusammengesetzte Indexe hinzufügen, die mit mehreren Filtern in der Abfrage übereinstimmen.

Sehen Sie sich diese Abfrage an:

Python

query_owner_size_tag = client.query(
        kind='Photo',
        filters=[('owner_id', '=', 'username'),
                 ('size', '=', 2),
                 ('tag', '=', 'family')])

Jeder Filter wird einem Indexscan in den folgenden integrierten Indexen zugeordnet:

    Index(Photo, owner_id)
    Index(Photo, size)
    Index(Photo, tag)
    

Wenn Sie den zusammengesetzten Index Index(Photo, owner_id, size) hinzufügen, wird die Abfrage zwei statt drei Indexscans zugeordnet:

    #  Satisfies both 'owner_id=username' and 'size=1'
    Index(Photo, owner_id, size)
    Index(Photo, tag)
    

Stellen Sie sich ein Szenario mit vielen großen Bildern vor, unter denen viele schwarz-weiße, aber wenige große Panoramabilder sind. Eine Abfragefilterung nach sowohl Panorama- als auch Schwarz-Weiß-Bildern wäre dann langsam, wenn die integrierten Indexe zusammengeführt werden:

Python

query_size_coloration = client.query(
        kind='Photo',
        filters=[('size', '=', 2),
                 ('coloration', '=', 1)])

Um die Abfrageleistung zu verbessern, können Sie den Wert von S (kleinster Satz von Entitäten in einem einzelnen Indexscan) auf O(S/(R * I)) senken, indem Sie den folgenden zusammengesetzten Index hinzufügen:

    Index(Photo, size, coloration)
    

Im Vergleich zur Verwendung von zwei integrierten Indexen erzeugt dieser zusammengesetzte Index weniger potenzielle Ergebnisse für dieselben zwei Abfragefilter. Dieser Ansatz verbessert die Leistung erheblich, wenn auf einen zweiten Index verzichtet wird.

Anzahl der zusammengesetzten Indexe mit Indexzusammenführung reduzieren

Obwohl zusammengesetzte Indexe, die genau mit den Filtern in einer Abfrage übereinstimmen, die beste Leistung erbringen, ist es nicht immer am besten oder möglich, einen zusammengesetzten Index für jede Filterkombination hinzuzufügen. Sie müssen Ihre zusammengesetzten Indexe gegen Folgendes abwägen:

  • Zusammengesetzte Indexlimits:

    Limit Wert
    Maximale Anzahl von zusammengesetzten Indexen für ein Projekt 200
    Maximale Summe der Größe von zusammengesetzten Indexeinträgen einer Entität 2 MiB
    Maximale Summe der folgenden Elemente für eine Entität:
    • Anzahl von indexierten Attributwerten
    • Anzahl von zusammengesetzten Indexeinträgen
    20.000
  • Speicherkosten für jeden zusätzlichen Index

Indexierungsprobleme treten häufig bei Feldern mit mehreren Werten wie dem tag-Attribut der Photo-Entitäten auf.

Angenommen, die Filterfunktion Photo muss absteigende Sortierklauseln anhand von vier zusätzlichen Attributen unterstützen:

Foto
Attribut Werttyp Beschreibung
date_added Ganzzahl Datum/Uhrzeit
rating Fließkommazahl Gesamtbewertung des Nutzers
comment_count Ganzzahl Anzahl der Kommentare
download_count Ganzzahl Anzahl der Downloads

Wenn Sie das Feld tag ignorieren, ist es möglich, zusammengesetzte Indexe auszuwählen, die mit jeder Kombination von Photo-Filtern übereinstimmen:

    Index(Photo, owner_id, -date_added)
    Index(Photo, owner_id, -comments)
    Index(Photo, size, -date_added)
    Index(Photo, size, -comments)
    ...
    Index(Photo, owner_id, size, -date_added)
    Index(Photo, owner_id, size, -comments)
    ...
    Index(Photo, owner_id, size, coloration, -date_added)
    Index(Photo, owner_id, size, coloration, -comments)
    

Die Gesamtzahl der zusammengesetzten Indexe ist:

    2^(number of filters) * (number of different orders) = 2 ^ 3 * 4 = 32 composite indexes
    

Wenn Sie versuchen, bis zu drei tag-Filter zu unterstützen, übersteigt die Gesamtzahl der zusammengesetzten Indexe das Limit von 200:

    2 ^ (3 + 3 tag filters) * 4 = 256 indexes.
    

Indexe, die Attribute mit mehreren Werten wie tag enthalten, führen außerdem zu Problemen mit explodierenden Indexen, die die Speicherkosten erhöhen.

Zur Unterstützung von Filtern im Feld tag für dieses Feature können Sie die Gesamtzahl der Indexe durch zusammengeführte Indexe reduzieren. Der folgende Satz zusammengesetzter Indexe ist das Minimum, das erforderlich ist, um die Filterfunktion Photo mit Sortierung zu unterstützen:

    Index(Photo, owner_id, -date_added)
    Index(Photo, owner_id, -rating)
    Index(Photo, owner_id, -comments)
    Index(Photo, owner_id, -downloads)
    Index(Photo, size, -date_added)
    Index(Photo, size, -rating)
    Index(Photo, size, -comments)
    Index(Photo, size, -downloads)
    ...
    Index(Photo, tag, -date_added)
    Index(Photo, tag, -rating)
    Index(Photo, tag, -comments)
    Index(Photo, tag, -downloads)
    

Die Anzahl der definierten zusammengesetzten Indexe ist:

    (number of filters + 1) * (number of orders) = 7 * 4 = 28
    

Die Indexzusammenführung bietet außerdem folgende Vorteile:

  • Sie ermöglicht einer Photo-Entität die Unterstützung von bis zu 1.000 Tags ohne Begrenzung der Anzahl der tag-Filter pro Abfrage.
  • Sie reduziert die Gesamtzahl der Indexe, wodurch die Speicherkosten sinken.

Indexe für Ihre Anwendung auswählen

Sie können optimale Indexe für Ihre Datenbank im Datastore-Modus auswählen, indem Sie zwei Ansätze verwenden:

  • Verwenden Sie die Indexzusammenführung, um zusätzliche Abfragen zu unterstützen

    • Erfordert weniger zusammengesetzte Indexe
    • Reduziert die Speicherkosten pro Entität
    • Vermeidet explodierende Indexe
    • Die Leistung hängt von der Form der Daten ab
  • Definieren Sie einen zusammengesetzten Index, der mit mehreren Filtern in einer Abfrage übereinstimmt

    • Verbessert die Abfrageleistung
    • Gleichbleibende Abfrageleistung, die nicht von der Form der Daten abhängt
    • Darf das Limit von 200 zusammengesetzten Indexen nicht überschreiten
    • Erhöhte Speicherkosten pro Entität

Die optimalen Indexe für Ihre Anwendung hängen von der Form Ihrer Daten ab. Wenn Sie die Abfrageleistung erst einmal mit Stichproben testen, bekommen Sie eine Vorstellung davon, welche Art von Abfragen bei Ihrer Anwendung häufig vorkommt und welche Abfragen langsam sind. Entsprechend den Ergebnissen Ihrer Stichproben können Sie Indexe hinzufügen, um die Leistung derjenigen Anfragen zu verbessern, die sowohl häufig vorkommen als auch langsam sind.