Ungefähre nächste Nachbarn finden, Vektorindizes erstellen und Vektoreinbettungen abfragen

Auf dieser Seite wird beschrieben, wie Sie mit den folgenden ANN-Distanzfunktionen in Spanner ungefähre nächste Nachbarn ermitteln, Vektorindizes erstellen und Vektoreinbettungen abfragen:

  • APPROX_COSINE_DISTANCE
  • APPROX_EUCLIDEAN_DISTANCE
  • APPROX_DOT_PRODUCT

Wenn ein Datensatz klein ist, können Sie die KNN-Suche (K-Nearest Neighbor) verwenden, um die genauen k nächsten Vektoren zu finden. Mit zunehmender Größe des Datensatzes steigen jedoch auch die Latenz und die Kosten einer KNN-Suche. Mit ANN können Sie die ungefähren k-nächsten Nachbarn mit deutlich reduzierter Latenz und Kosten ermitteln.

Ungefähre K-nächstgelegenen Nachbarn

Bei einer ANN-Suche sind die zurückgegebenen Vektoren nicht die tatsächlichen k nächsten Nachbarn. Gelegentlich werden einige Vektoren zurückgegeben, die nicht zu den k nächsten Nachbarn gehören. Dies wird als Erinnerungsverlust bezeichnet. Wie groß der Verlust der Abrufquote für Sie akzeptabel ist, hängt vom Anwendungsfall ab. In den meisten Fällen ist es jedoch ein akzeptabler Kompromiss, wenn Sie im Gegenzug für eine verbesserte Datenbankleistung etwas an der Abrufquote einbüßen.

Weitere Informationen zu den Funktionen für ungefähre Entfernungen in Spanner finden Sie unter:

Vektorindex

Spanner beschleunigt ANN-Vektorsuchen mithilfe eines speziellen Vektorindexes. Dieser Index nutzt den Scalable Nearest Neighbor (ScaNN) von Google Research, einen hocheffizienten Algorithmus für die Suche nach dem nächsten Nachbarn.

Der Vektorindex verwendet eine baumbasierte Struktur, um Daten zu partitionieren und schnellere Suchanfragen zu ermöglichen. Spanner bietet sowohl zweistufige als auch dreistufige Baumkonfigurationen:

  • Zweistufige Baumkonfiguration: Endknoten (num_leaves) enthalten Gruppen eng miteinander verwandter Vektoren sowie deren entsprechenden Schwerpunkt. Die Wurzelebene besteht aus den Schwerpunkten aller Blattknoten.
  • Dreistufige Baumkonfiguration: Ähnlich wie ein zweistufiger Baum, jedoch mit einer zusätzlichen Verzweigungsebene (num_branches), von der aus die Centroide der Blätter weiter partitioniert werden, um die Wurzelebene (num_leaves) zu bilden.

Außerdem müssen Sie Ihren Vektorindex mit einem bestimmten Entfernungsmesswert erstellen. Sie können den für Ihren Anwendungsfall am besten geeigneten Entfernungsmesswert auswählen, indem Sie distance_type auf einen der Werte COSINE, DOT_PRODUCT oder EUCLIDEAN festlegen.

Weitere Informationen finden Sie unter VECTOR INDEX-Anweisungen.

Beschränkungen

Für den Spanner-Vektorindex gelten die folgenden Einschränkungen:

  • ALTER VECTOR INDEX wird nicht unterstützt.

Vektorindex erstellen

Um den Vektorindex für eine gute Wiedererkennung und Leistung zu optimieren, empfehlen wir, ihn zu erstellen, nachdem die meisten Zeilen mit Einbettungen in Ihre Datenbank geschrieben wurden. Möglicherweise müssen Sie den Vektorindex auch regelmäßig neu erstellen, nachdem Sie neue Daten eingefügt haben. Weitere Informationen finden Sie unter Vektorindex neu erstellen.

So erstellen Sie einen Vektorindex mit einem zweistufigen Baum und 1.000 Blattknoten in einer Documents-Tabelle mit einer Einbettungsspalte DocEmbedding unter Verwendung des Kosinusabstands:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(DocEmbedding)
  OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);

So erstellen Sie einen Vektorindex mit einem dreistufigen Baum und 1.000.000 Blattknoten:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(NullableDocEmbedding)
  WHERE NullableDocEmbedding IS NOT NULL
  OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);

Wenn die Spalte für die Einbettung nullable ist, müssen Sie sie mit einer WHERE column_name IS NOT NULL-Klausel deklarieren:

CREATE VECTOR INDEX DocEmbeddingIndex
  ON Documents(NullableDocEmbedding)
  WHERE NullableDocEmbedding IS NOT NULL
  OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);

Vektoreinbettungen abfragen

Verwenden Sie eine der drei Näherungsfunktionen für die Entfernung, um einen Vektorindex abzufragen:

  • APPROX_COSINE_DISTANCE
  • APPROX_EUCLIDEAN_DISTANCE
  • APPROX_DOT_PRODUCT

Für die Verwendung der Funktionen für die ungefähre Entfernung gelten die folgenden Einschränkungen:

  • Sie müssen einen Abfragehinweis angeben, um den Vektorindex zu verwenden.
  • Sie müssen als Argument der Entfernungsfunktion einen konstanten Ausdruck verwenden, z. B. einen Parameter oder ein Literal.
  • Die Abfrage oder untergeordnete Abfrage, in der die Funktion „Etwaige Entfernung“ verwendet wird, muss eine bestimmte Form haben: Die Entfernungsfunktion muss der einzige ORDER BY-Schlüssel sein und es muss ein Limit angegeben werden.

Eine detaillierte Liste der Einschränkungen finden Sie auf der Referenzseite der Funktion „Ungefähre Entfernung“.

Beispiel

So suchen Sie nach den 100 nächsten Vektoren zu [1.0, 2.0, 3.0]:

SELECT DocId
FROM Documents@{FORCE_INDEX=DocEmbeddingIndex}
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

Wenn die Spalte für die Einbettung Nullwerte enthalten kann:

SELECT DocId
FROM Documents@{FORCE_INDEX=DocEmbeddingIndex}
WHERE NullableDocEmbedding IS NOT NULL
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], NullableDocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

Best Practices

Mit den folgenden Best Practices können Sie Ihre Vektorindexe optimieren und die Abfrageergebnisse verbessern.

Vektorsuchoptionen optimieren

Der optimale Wert für die Vektorsuche hängt vom Anwendungsfall, dem Vektordatensatz und den Abfragevektoren ab. Möglicherweise müssen Sie die Werte iterativ optimieren, um die besten Werte für Ihre spezifische Arbeitslast zu finden.

Hier sind einige hilfreiche Richtlinien für die Auswahl geeigneter Werte:

  • tree_depth (Baumebene): Wenn die indexierte Tabelle weniger als 10 Millionen Zeilen hat, verwenden Sie 2 als tree_depth. Andernfalls werden mit einem tree_depth von 3 Tabellen mit bis zu etwa 10 Milliarden Zeilen unterstützt.

  • num_leaves: Die Quadratwurzel der Anzahl der Zeilen im Dataset verwenden. Ein höherer Wert kann die Erstellungszeit des Vektorindexes verlängern. Legen Sie num_leaves nicht höher als table_row_count/1000 fest, da dies zu zu kleinen Blättern und einer schlechten Leistung führt.

  • num_leaves_to_search: Mit dieser Option wird festgelegt, wie viele Blattknoten des Index durchsucht werden. Durch eine Erhöhung von num_leaves_to_search wird der Recall verbessert, aber auch die Latenz und die Kosten. Wir empfehlen, als Wert für num_leaves_to_search eine Zahl zu verwenden, die 1% der Gesamtzahl der Blätter entspricht, die in der CREATE VECTOR INDEX-Anweisung definiert sind. Wenn Sie eine Filterklausel verwenden, erhöhen Sie diesen Wert, um die Suche zu erweitern.

Wenn ein akzeptabler Recall erreicht wird, die Abfragekosten aber zu hoch sind, was zu einer niedrigen maximalen QPS führt, können Sie num_leaves erhöhen. Gehen Sie dazu so vor:

  1. Legen Sie num_leaves auf ein Vielfaches k des ursprünglichen Werts fest (z. B. 2 * sqrt(table_row_count)).
  2. Legen Sie num_leaves_to_search auf das gleiche Vielfache k des ursprünglichen Werts fest.
  3. Versuchen Sie, num_leaves_to_search zu reduzieren, um die Kosten und die Anzahl der Abfragen pro Sekunde zu verbessern und gleichzeitig den Recall beizubehalten.

Erinnerung verbessern

Es gibt mehrere Möglichkeiten, wie sich die Erinnerung verschlechtern kann:

  • num_leaves_to_search ist zu klein: Bei einigen Abfragevektoren ist es möglicherweise schwieriger, die nächsten Nachbarn zu finden. Wenn Sie num_leaves_to_search erhöhen, um mehr Blätter zu durchsuchen, kann sich die Trefferquote verbessern. In letzter Zeit wurden möglicherweise mehr dieser schwierigen Vektoren verwendet.

  • Der Vektorindex muss neu erstellt werden: Die Baumstruktur des Vektorindexes wird beim Erstellen für den Datensatz optimiert und ist danach statisch. Wenn also nach dem Erstellen des ersten Vektorindexes deutlich unterschiedliche Vektoren hinzugefügt werden, ist die Baumstruktur möglicherweise nicht optimal, was zu einer schlechteren Erkennungsleistung führt.

Vektorindex neu erstellen

So erstellen Sie Ihren Vektorindex ohne Ausfallzeit neu:

  1. Erstellen Sie einen neuen Vektorindex in derselben Einbettungsspalte wie der aktuelle Vektorindex und aktualisieren Sie gegebenenfalls die Parameter (z. B. OPTIONS).
  2. Nachdem die Indexerstellung abgeschlossen ist, ändern Sie den FORCE_INDEX-Hinweis so, dass er auf den neuen Index verweist, um die Vektorsuchabfrage zu aktualisieren. Dadurch wird sichergestellt, dass für die Abfrage der neue Vektorindex verwendet wird. Möglicherweise müssen Sie auch num_leaves_to_search in Ihrer neuen Abfrage neu anpassen.
  3. Löschen Sie den veralteten Vektorindex.

Nächste Schritte