Cette page explique comment trouver les plus proches voisins approximatifs (ANN) et interroger les embeddings vectoriels à l'aide des fonctions de distance ANN.
Lorsqu'un ensemble de données est petit, vous pouvez utiliser K-nearest neighbors (KNN) pour trouver les k vecteurs les plus proches exacts. Toutefois, à mesure que votre ensemble de données augmente, la latence et le coût d'une recherche KNN augmentent également. Vous pouvez utiliser ANN pour trouver les k-plus proches voisins approximatifs avec une latence et des coûts considérablement réduits.
Dans une recherche ANN, les k vecteurs renvoyés ne sont pas les k voisins les plus proches, car la recherche ANN calcule des distances approximatives et peut ne pas examiner tous les vecteurs de l'ensemble de données. Il arrive que quelques vecteurs qui ne figurent pas parmi les k-voisins les plus proches soient renvoyés. C'est ce qu'on appelle la perte de couverture. La perte de rappel acceptable dépend de votre cas d'utilisation. Toutefois, dans la plupart des cas, il est acceptable de perdre un peu de rappel en échange d'une amélioration des performances de la base de données.
Pour en savoir plus sur les fonctions de distance approximative compatibles avec Spanner, consultez les pages de référence suivantes pour votre dialecte de base de données :
- GoogleSQL
- PostgreSQL
Interroger les embeddings vectoriels
Spanner accélère les recherches vectorielles des plus proches voisins approximatifs (ANN) en utilisant un index vectoriel. Vous pouvez utiliser un index vectoriel pour interroger des embeddings vectoriels. Pour interroger des embeddings vectoriels, vous devez d'abord créer un index vectoriel. Vous pouvez ensuite utiliser l'une des trois fonctions de distance approximative pour trouver l'ANN.
Les restrictions suivantes s'appliquent lorsque vous utilisez les fonctions de distance approximative :
- La fonction de distance approximative doit calculer la distance entre une colonne d'embedding et une expression constante (par exemple, un paramètre ou un littéral).
- La sortie de la fonction de distance approximative doit être utilisée dans une clause
ORDER BYcomme seule clé de tri, et unLIMITdoit être spécifié après leORDER BY. - La requête doit filtrer explicitement les lignes qui ne sont pas indexées. Dans la plupart des cas, cela signifie que la requête doit inclure une clause
WHERE <column_name> IS NOT NULLqui correspond à la définition de l'index vectoriel, sauf si la colonne est déjà marquée commeNOT NULLdans la définition de la table.
Pour obtenir la liste détaillée des limites, consultez la page de référence sur la fonction de distance approximative.
Exemples
Prenons l'exemple d'une table Documents comportant une colonne DocEmbedding d'embeddings de texte précalculés à partir de la colonne d'octets DocContents et une colonne NullableDocEmbedding renseignée à partir d'autres sources, qui peut être nulle.
GoogleSQL
CREATE TABLE Documents (
UserId INT64 NOT NULL,
DocId INT64 NOT NULL,
Author STRING(1024),
DocContents BYTES(MAX),
DocEmbedding ARRAY<FLOAT32> NOT NULL,
NullableDocEmbedding ARRAY<FLOAT32>,
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[] not null,
nullable_doc_embedding float4[],
word_count bigint,
PRIMARY KEY (user_id, doc_id)
);
Pour rechercher les 100 vecteurs les plus proches de [1.0, 2.0, 3.0] :
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;
Pour rechercher les 100 vecteurs les plus proches d'un embedding généré par une expression SQL, utilisez le modèle suivant. Dans cet exemple, la requête recherche les documents les plus semblables à l'embedding de UserId = 1 et DocId = 1 :
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
Si la colonne d'embedding peut avoir une valeur nulle :
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;
Étapes suivantes
En savoir plus sur les index vectoriels Spanner
En savoir plus sur les fonctions de distance approximative dans GoogleSQL et PostgreSQL
En savoir plus sur les instructions d'index pour GoogleSQL
VECTOR INDEXet PostgreSQLINDEXEn savoir plus sur les bonnes pratiques concernant les index vectoriels
Essayez Premiers pas avec la recherche vectorielle Spanner pour obtenir un exemple détaillé d'utilisation d'ANN.