Auf dieser Seite wird beschrieben, wie Sie mit den folgenden ANN-Entfernungsfunktionen in Spanner die ungefähren nächsten Nachbarn (ANN) ermitteln, Vektorindexe erstellen und Vektoreinbettungen abfragen:
APPROX_COSINE_DISTANCE
APPROX_EUCLIDEAN_DISTANCE
APPROX_DOT_PRODUCT
Wenn ein Dataset klein ist, können Sie k-nächstgelegene Nachbarn (KNN) verwenden, um die genauen k-nächsten Vektoren zu ermitteln. Wenn Ihr Dataset jedoch wächst, steigen auch die Latenz und die Kosten einer KNN-Suche. Sie können ANN verwenden, um die ungefähren k-nächsten Nachbarn mit erheblich geringerer Latenz und geringeren Kosten zu ermitteln.
Ungefähre k-nächste Nachbarn
Bei einer ANN-Suche sind die k-zurückgegebenen Vektoren nicht die tatsächlichen k-nächsten Nachbarn, da die ANN-Suche ungefähre Entfernungen berechnet und möglicherweise nicht alle Vektoren im Datensatz berücksichtigt. Gelegentlich werden einige Vektoren zurückgegeben, die nicht zu den obersten k-nächsten Nachbarn gehören. Das wird als Rückrufverlust bezeichnet. Wie viel der Recall-Verlust für Sie akzeptabel ist, hängt vom Anwendungsfall ab. In den meisten Fällen ist jedoch ein geringer Recall im Gegenzug für eine verbesserte Datenbankleistung ein akzeptabler Kompromiss.
Weitere Informationen zu den Spanner-Funktionen für die ungefähre Entfernung finden Sie unter:
APPROX_COSINE_DISTANCE
in GoogleSQLAPPROX_EUCLIDEAN_DISTANCE
in GoogleSQLAPPROX_DOT_PRODUCT
in GoogleSQL
Vektorindex
Spanner beschleunigt die ANN-Vektorsuche mithilfe eines spezialisierten Vektorindex. Dieser Index nutzt den skalierbaren nächsten Nachbarn (ScaNN) von Google Research, einen hocheffizienten Algorithmus für den nächsten Nachbarn.
Der Vektorindex verwendet eine baumbasierte Struktur, um Daten zu partitionieren und schnellere Suchvorgänge zu ermöglichen. Spanner bietet sowohl Baumkonfigurationen mit zwei als auch mit drei Ebenen:
- Baumkonfiguration auf zwei Ebenen: Blattknoten (
num_leaves
) enthalten Gruppen eng verwandter Vektoren und ihren entsprechenden Schwerpunkt. Die Stammebene besteht aus den Schwerpunkten aller Blattknoten. - Baumkonfiguration mit drei Ebenen: Ähnlich wie ein Baum mit zwei Ebenen, mit dem Unterschied, dass eine zusätzliche Zweigebene (
num_branches
) eingeführt wird, von der Blattknotenschwerpunkte weiter partitioniert werden, um die Stammebene (num_leaves
) zu bilden.
Spanner wählt einen Index für Sie aus. Wenn Sie jedoch wissen, dass ein bestimmter Index am besten funktioniert, können Sie den FORCE_INDEX
-Hinweis verwenden, um den am besten geeigneten Vektorindex für Ihren Anwendungsfall zu verwenden.
Weitere Informationen findest du unter VECTOR INDEX
-Anweisungen.
Beschränkungen
- Sie können Vektorindexe nicht im Voraus aufteilen. Weitere Informationen finden Sie unter Übersicht über die Vorabaufteilung.
Vektorindex erstellen
Um die Trefferquote und die Leistung eines Vektorindex zu optimieren, empfehlen wir Folgendes:
Erstellen Sie den Vektorindex, nachdem die meisten Zeilen mit Einbettungen in die 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.
Mit der
STORING
-Klausel können Sie eine Kopie einer Spalte im Vektorindex speichern. Wenn ein Spaltenwert im Vektorindex gespeichert ist, filtert Spanner auf der Blattebene des Index, um die Abfrageleistung zu verbessern. Wir empfehlen, eine Spalte zu speichern, wenn sie in einer Filterbedingung verwendet wird. Weitere Informationen zur Verwendung vonSTORING
in einem Index finden Sie unter Index für reine Indexscans erstellen.
Beim Erstellen der Tabelle muss die Einbettungsspalte ein Array des Datentyps FLOAT32
(empfohlen) oder FLOAT64
sein und die Anmerkung vector_length haben, die die Dimension der Vektoren angibt.
Mit der folgenden DDL-Anweisung wird eine Documents
-Tabelle mit einer Einbettungsspalte DocEmbedding
mit einer Vektorlänge erstellt:
CREATE TABLE Documents {
...
DocEmbedding ARRAY<FLOAT32>(vector_length=>128);
};
Nachdem Sie die Tabelle Documents
ausgefüllt haben, können Sie einen Vektorindex mit einer zweistufigen Baumstruktur und 1.000 Blattknoten in einer Documents
-Tabelle mit einer Einbettungsspalte DocEmbedding
unter Verwendung der Kosinus-Distanz erstellen:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(DocEmbedding)
STORING (WordCount)
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
So erstellen Sie einen Vektorindex mit einer Baumstruktur mit drei Ebenen und 1.000.000 Blattknoten:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(NullableDocEmbedding)
STORING (WordCount)
WHERE NullableDocEmbedding IS NOT NULL
OPTIONS (distance_type = 'COSINE', tree_depth = 3, num_branches=1000, num_leaves = 1000000);
Wenn die Einbettungsspalte in der Tabellendefinition nicht als NOT NULL gekennzeichnet ist, müssen Sie sie mit einer WHERE column_name IS NOT NULL
-Klausel deklarieren:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(NullableDocEmbedding)
STORING (WordCount)
WHERE NullableDocEmbedding IS NOT NULL
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Vektoreinbettungen abfragen
Verwenden Sie zum Abfragen eines Vektorindex eine der drei ungefähren Entfernungsfunktionen:
APPROX_COSINE_DISTANCE
APPROX_EUCLIDEAN_DISTANCE
APPROX_DOT_PRODUCT
Zu den Einschränkungen bei der Verwendung der Funktionen für ungefähre Entfernungen gehören:
- Mit der Funktion für ungefähre Entfernungen muss die Entfernung zwischen einer eingebetteten Spalte und einem konstanten Ausdruck (z. B. einem Parameter oder Literal) berechnet werden.
- Die Ausgabe der Funktion für die ungefähre Entfernung muss in einer
ORDER BY
-Klausel als einzigen Sortierschlüssel verwendet werden und nachORDER BY
muss einLIMIT
angegeben werden. - Die Abfrage muss Zeilen, die nicht indexiert sind, explizit herausfiltern. In den meisten Fällen bedeutet dies, dass die Abfrage eine
WHERE <column_name> IS NOT NULL
-Klausel enthalten muss, die der Vektorindexdefinition entspricht, es sei denn, die Spalte ist in der Tabellendefinition bereits alsNOT NULL
gekennzeichnet.
Eine ausführliche Liste der Einschränkungen finden Sie auf der Referenzseite für ungefähre Entfernungsfunktionen.
Beispiel
So suchen Sie nach den nächsten 100 Vektoren, die [1.0, 2.0, 3.0]
entsprechen:
SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100
Wenn für die Einbettungsspalte Nullwerte zulässig sind:
SELECT DocId
FROM Documents
WHERE NullableDocEmbedding IS NOT NULL AND WordCount > 1000
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
Befolgen Sie diese Best Practices, um Ihre Vektorindexe zu optimieren und Abfrageergebnisse zu verbessern.
Optionen für die Vektorsuche abstimmen
Der optimale Wert für die Vektorsuche ist vom Anwendungsfall, vom Vektor-Dataset und von den Abfragevektoren abhängig. Möglicherweise müssen Sie eine iterative Abstimmung durchführen, um die besten Werte für Ihre spezifische Arbeitslast zu finden.
Hier sind einige hilfreiche Richtlinien, die Sie bei der Auswahl geeigneter Werte beachten sollten:
tree_depth
(Baumebene): Wenn die indexierte Tabelle weniger als 10 Millionen Zeilen hat, verwenden Sie fürtree_depth
den Wert2
. Andernfalls unterstützt eintree_depth
von3
Tabellen mit bis zu etwa 10 Milliarden Zeilen.num_leaves
: Verwendet die Quadratwurzel der Zeilenanzahl im Dataset. Ein höherer Wert kann die Erstellungszeit des Vektorindex erhöhen.num_leaves
sollte nicht größer alstable_row_count/1000
sein. Dies führt zu übermäßig kleinen Blättern und einer schlechten Leistung.num_leaves_to_search
: Diese Option gibt an, wie viele Blattknoten des Index durchsucht werden. Ein Erhöhen vonnum_leaves_to_search
verbessert die Trefferquote, erhöht aber auch die Latenz und die Kosten. Als Wert fürnum_leaves_to_search
empfehlen wir eine Zahl, die 1% der Gesamtzahl der Blätter entspricht, die in derCREATE 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 jedoch zu hoch sind und die maximale Anzahl von Abfragen pro Sekunde zu niedrig ist, versuchen Sie, num_leaves
zu erhöhen. Gehen Sie dazu so vor:
- Legen Sie
num_leaves
auf einige mehrere k seines ursprünglichen Werts fest (z. B.2 * sqrt(table_row_count)
). - Legen Sie für
num_leaves_to_search
das gleiche Vielfache der k-Werte des ursprünglichen Werts fest. - Experimentieren Sie mit einer Reduzierung von
num_leaves_to_search
, um die Kosten und die Abfragen pro Sekunde zu senken und gleichzeitig die Recall-Funktion aufrechtzuerhalten.
Erinnerung verbessern
Es gibt mehrere Möglichkeiten für eine Verschlechterung der Erinnerung, darunter:
num_leaves_to_search
ist zu klein: Bei einigen Abfragevektoren ist es möglicherweise schwieriger, die nächsten Nachbarn zu finden. Wenn Sie alsonum_leaves_to_search
erhöhen, um nach mehr Blättern zu suchen, kann die Trefferquote verbessert werden. Die letzten Abfragen haben sich möglicherweise verschoben, um mehr dieser anspruchsvollen Vektoren zu enthalten.Der Vektorindex muss neu erstellt werden: Die Baumstruktur des Vektorindex ist zum Zeitpunkt der Erstellung für den Datensatz optimiert und danach statisch. Wenn also nach dem Erstellen des ersten Vektorindex deutlich unterschiedliche Vektoren hinzugefügt werden, ist die Baumstruktur möglicherweise nicht optimal, was zu einer schlechten Trefferquote führt.
Vektorindex neu erstellen
So erstellen Sie Ihren Vektorindex ohne Ausfallzeit neu:
- Erstellen Sie einen neuen Vektorindex in derselben Einbettungsspalte wie der aktuelle Vektorindex und aktualisieren Sie die Parameter (z. B.
OPTIONS
) nach Bedarf. - Verwenden Sie nach Abschluss der Indexerstellung den Hinweis
FORCE_INDEX
, um auf den neuen Index zu verweisen und die Vektorsuchabfrage zu aktualisieren. Dadurch wird sichergestellt, dass die Abfrage den neuen Vektorindex verwendet. Möglicherweise müssen Sie auchnum_leaves_to_search
in Ihrer neuen Abfrage anpassen. - Löschen Sie den veralteten Vektorindex.
Nächste Schritte
Weitere Informationen zu den GoogleSQL-Funktionen
APPROXIMATE_COSINE_DISTANCE()
,APPROXIMATE_EUCLIDEAN_DISTANCE()
,APPROXIMATE_DOT_PRODUCT()
Unter Erste Schritte mit der Spanner-Vektorsuche finden Sie ein detailliertes Beispiel zur Verwendung von ANN.