Ungefähre nächste Nachbarn (Approximate Nearest Neighbors, ANN) und Abfragevektoreinbettungen finden

Auf dieser Seite wird beschrieben, wie Sie mit den ANN-Distanzfunktionen ungefähre nächste Nachbarn (ANN) finden und Vektoreinbettungen abfragen.

Wenn ein Dataset klein ist, können Sie K-Nearest Neighbors (KNN) verwenden, um die genauen k-nächsten Vektoren zu finden. Mit zunehmender Größe des Datasets 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 finden.

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 Dataset berücksichtigt. Gelegentlich werden einige Vektoren zurückgegeben, die nicht zu den k nächsten Nachbarn gehören. Dies wird als Recall-Verlust bezeichnet. Wie viel Trefferquotenverlust für Sie akzeptabel ist, hängt vom Anwendungsfall ab. In den meisten Fällen ist ein geringer Trefferquotenverlust im Gegenzug für eine verbesserte Datenbankleistung jedoch ein akzeptabler Kompromiss.

Weitere Informationen zu den in Spanner unterstützten Funktionen für ungefähre Entfernungen finden Sie auf den folgenden Referenzseiten für Ihren Datenbankdialekt:

Vektoreinbettungen abfragen

Cloud Spanner beschleunigt die Vektorsuche nach dem ungefähren nächsten Nachbarn (Approximate Nearest Neighbor, ANN) mithilfe eines Vektorindex. Sie können einen Vektorindex verwenden, um Vektoreinbettungen abzufragen. Wenn Sie Vektoreinbettungen abfragen möchten, müssen Sie zuerst einen Vektorindex erstellen. Anschließend können Sie eine der drei ungefähren Distanzfunktionen verwenden, um das ANN zu finden.

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

  • Die Funktion für die ungefähre Entfernung muss die Entfernung zwischen einer Einbettungsspalte und einem konstanten Ausdruck (z. B. einem Parameter oder einem Literal) berechnen.
  • Die Ausgabe der Funktion für die ungefähre Entfernung muss in einer ORDER BY-Klausel als einziger Sortierschlüssel verwendet werden und nach der ORDER BY-Klausel muss ein LIMIT angegeben werden.
  • In der Abfrage müssen Zeilen, die nicht indexiert sind, explizit herausgefiltert werden. 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 als NOT NULL gekennzeichnet.

Eine detaillierte Liste der Einschränkungen finden Sie auf der Referenzseite für die Funktion zur ungefähren Entfernung.

Beispiele

Angenommen, Sie haben eine Documents-Tabelle mit einer DocEmbedding-Spalte mit vorkalkulierten Texteinbettungen aus der DocContents-Byte-Spalte und einer NullableDocEmbedding-Spalte, die aus anderen Quellen gefüllt wird und null sein kann. Beide Einbettungsspalten geben eine Vektorlänge von 3 an, die erforderlich ist, um einen Vektorindex für die ANN-Suche zu erstellen.

GoogleSQL

CREATE TABLE Documents (
  UserId       INT64 NOT NULL,
  DocId        INT64 NOT NULL,
  Author       STRING(1024),
  DocContents  BYTES(MAX),
  DocEmbedding ARRAY<FLOAT32>(vector_length=>3) NOT NULL,
  NullableDocEmbedding ARRAY<FLOAT32>(vector_length=>3),
  WordCount    INT64
) PRIMARY KEY (UserId, DocId);

PostgreSQL

CREATE TABLE documents (
  user_id      bigint not null,
  doc_id       bigint not null,
  author       varchar(1024),
  doc_contents bytea,
  doc_embedding float4[] VECTOR LENGTH 3 not null,
  nullable_doc_embedding float4[] VECTOR LENGTH 3,
  word_count   bigint,
  PRIMARY KEY (user_id, doc_id)
);

Wenn Sie nach den 100 Vektoren suchen möchten, die [1.0, 2.0, 3.0] am nächsten sind, geben Sie eine der folgenden Suchoptionen in der Funktion für die ungefähre Distanz an:

  • num_leaves_to_search: Die Anzahl der zu durchsuchenden Blätter. Der Wert muss eine positive Ganzzahl sein.
  • pct_leaves_to_search: Der Prozentsatz der zu durchsuchenden Blätter. Der Wert muss ein Double zwischen 0.0 und 100.0 mit einem expliziten Dezimalpunkt sein (z. B. 10.0). Vektorindexe, die vor November 2025 erstellt wurden, unterstützen diese Suchoption möglicherweise nicht.

Sie können nicht beide Optionen in derselben Funktion für die ungefähre Entfernung angeben.

Option 1: Suchoption „num_leaves_to_search“ verwenden

GoogleSQL

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

PostgreSQL

SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
  options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;

Option 2: Suchoption „pct_leaves_to_search“ verwenden

GoogleSQL

SELECT DocId
FROM Documents
WHERE WordCount > 1000
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  ARRAY<FLOAT32>[1.0, 2.0, 3.0], DocEmbedding,
  options => JSON '{"pct_leaves_to_search": 10.0}')
LIMIT 100

PostgreSQL

SELECT doc_id
FROM documents
WHERE word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], doc_embedding,
  options=>jsonb'{"pct_leaves_to_search": 10.0}'
)
LIMIT 100;

Verwenden Sie das folgende Muster, um nach den 100 Vektoren zu suchen, die einer Einbettung am nächsten sind, die von einem SQL-Ausdruck generiert wird. In diesem Beispiel werden mit der Abfrage die Dokumente gesucht, die der Einbettung von UserId = 1 und DocId = 1 am ähnlichsten sind:

GoogleSQL

WITH emb AS (
  SELECT DocEmbedding AS value
  FROM Documents
  WHERE UserId = 1 AND DocId = 1
  LIMIT 1
)
SELECT DocId
FROM Documents, emb
ORDER BY APPROX_EUCLIDEAN_DISTANCE(
  emb.value, DocEmbedding,
  options => JSON '{"num_leaves_to_search": 10}')
LIMIT 100

PostgreSQL

SELECT documents.doc_id
FROM
  documents,
  (
    SELECT doc_embedding AS value
    FROM documents
    WHERE user_id = 1 AND doc_id = 1
    LIMIT 1
  ) vector
WHERE documents.doc_embedding IS NOT NULL
ORDER BY spanner.APPROX_EUCLIDEAN_DISTANCE(documents.doc_embedding,
         vector.value, options=>'{"num_leaves_to_search": 10}'::jsonb)
LIMIT 100

Wenn die Einbettungsspalte Nullwerte enthalten kann:

GoogleSQL

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

PostgreSQL

SELECT doc_id
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY spanner.approx_euclidean_distance(
  ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
  options=>jsonb'{"num_leaves_to_search": 10}'
)
LIMIT 100;

Entfernung zu den Abfrageergebnissen hinzufügen

In den vorherigen Beispielen wird die ANN-Distanz verwendet, um die Abfrageergebnisse zu sortieren, sie wird jedoch nicht in diesen Ergebnissen angezeigt. Wenn Sie die Entfernung zu den Ergebnissen hinzufügen möchten, platzieren Sie die Entfernungsfunktion in der SELECT-Klausel und weisen Sie ihr einen Alias zu. Verwenden Sie diesen Alias dann als einzigen Sortierschlüssel in der ORDER BY-Klausel.

Beispiele

GoogleSQL

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

PostgreSQL

SELECT doc_id,
  spanner.approx_euclidean_distance(
    ARRAY[1.0, 2.0, 3.0]::float4[], nullable_doc_embedding,
    options=>jsonb'{"num_leaves_to_search": 10}'
  ) AS distance
FROM documents
WHERE nullable_doc_embedding IS NOT NULL AND word_count > 1000
ORDER BY distance
LIMIT 100;

Nächste Schritte