Cette page explique comment créer un indice vectoriel et interroger des représentations vectorielles continues à l'aide des fonctions de distance cosinus approximative, de distance euclidienne approximative et de produit scalaire vectoriel approximatif. Vous pouvez utiliser ces pour trouver les voisins les plus proches (ANN) dans Spanner. Lorsqu'un ensemble de données est petit, vous pouvez utiliser l'algorithme des k plus proches voisins (KNN) pour trouver les vecteurs k les plus proches. Toutefois, à mesure que votre ensemble de données augmente, la latence et le coût d'une recherche KNN augmentent également. Vous pouvez utiliser une ANN pour trouver les k plus proches voisins approximatifs avec une latence et des coûts considérablement réduits.
Voisins les plus proches approximatifs
Dans une recherche ANN, les vecteurs k renvoyés ne sont pas les vrais k voisins les plus proches. Parfois, quelques vecteurs qui ne figurent pas parmi les k premiers k les plus proches les voisins sont renvoyés. C'est ce que l'on appelle la perte de rappel. Le niveau de perte de rappel acceptable pour vous dépend du cas d'utilisation, mais dans la plupart des cas, perdre un peu de rappel en échange d'une amélioration des performances de la base de données est un compromis acceptable.
Pour en savoir plus sur les fonctions de distance approximative Spanner, consultez les pages suivantes :
APPROX_COSINE_DISTANCE
dans GoogleSQLAPPROX_EUCLIDEAN_DISTANCE
dans GoogleSQLAPPROX_DOT_PRODUCT
dans GoogleSQL
Index vectoriel
Spanner accélère les recherches vectorielles ANN à l'aide d'un index vectoriel spécialisé. Cet index s'appuie sur ScaNN (Scalable Nearest Neighbor), un algorithme de voisin le plus proche très efficace développé par Google Research.
L'index vectoriel utilise une structure arborescente pour partitionner les données et faciliter des recherches plus rapides. Spanner propose des configurations d'arborescences à deux et trois niveaux :
- Arborescence à deux niveaux: les nœuds feuille (
num_leaves
) contiennent des groupes de de vecteurs étroitement liés et de leur centroïde correspondant. Le niveau racine se compose des centroïdes de tous les nœuds de feuille. - Arborescence à trois niveaux: conceptuelle semblable à une arborescence à deux niveaux,
ajout d'une couche de ramification (
num_branches
), à partir de laquelle le nœud feuille les centroïdes sont ensuite partitionnés pour former le niveau racine (num_leaves
).
En outre, vous devez créer votre index vectoriel avec une métrique de distance spécifique.
Vous pouvez choisir la métrique de distance la plus adaptée à votre cas d'utilisation en définissant
distance_type
sur COSINE
, DOT_PRODUCT
ou EUCLIDEAN
.
Pour en savoir plus, consultez Instructions VECTOR INDEX
.
Limites
L'index vectoriel Spanner présente les limites suivantes:
ALTER VECTOR INDEX
n'est pas compatible.
Créer un index vectoriel
Pour optimiser au mieux l'index vectoriel afin d'obtenir un bon rappel et de bonnes performances, nous vous recommandons de créer votre index vectoriel une fois que la plupart des lignes contenant des représentations vectorielles continues ont été écrites dans votre base de données. Vous devrez peut-être également reconstruire régulièrement l'index vectoriel après avoir inséré de nouvelles données. Pour en savoir plus, consultez Reconstruisez l'index vectoriel.
Pour créer un index vectoriel avec une arborescence à deux niveaux et 1 000 nœuds feuilles sur un
Table Documents
avec une colonne de représentation vectorielle continue DocEmbedding
utilisant le cosinus
distance:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(DocEmbedding)
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Pour créer un index vectoriel avec une arborescence à trois niveaux et 1 000 000 nœuds feuilles:
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);
Si votre colonne de représentations vectorielles continues peut avoir une valeur nulle, vous devez la déclarer avec une
Clause WHERE column_name IS NOT NULL
:
CREATE VECTOR INDEX DocEmbeddingIndex
ON Documents(NullableDocEmbedding)
WHERE NullableDocEmbedding IS NOT NULL
OPTIONS (distance_type = 'COSINE', tree_depth = 2, num_leaves = 1000);
Interroger les embeddings vectoriels
Pour interroger un index vectoriel, utilisez l'une des trois fonctions de distance approximative:
APPROX_COSINE_DISTANCE
APPROX_EUCLIDEAN_DISTANCE
APPROX_DOT_PRODUCT
Lorsque vous utilisez les fonctions de distance approximative, certaines restrictions s'appliquent, entre autres : suivantes:
- Vous devez fournir un indice de requête pour utiliser l'index vectoriel.
- Vous devez utiliser une expression constante comme argument de la fonction de distance (par exemple, un paramètre ou un littéral).
- La requête ou sous-requête dans laquelle la fonction de distance approximative est utilisée doit
prennent une forme spécifique: la fonction de distance doit être la seule touche
ORDER BY
, et une limite doit être spécifiée.
Pour obtenir la liste détaillée des limites, reportez-vous au page de référence sur la fonction de distance approximative.
Exemple
Pour rechercher les 100 vecteurs les plus proches de [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
Si la colonne de représentations vectorielles continues peut avoir une valeur nulle:
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
Bonnes pratiques
Suivez ces bonnes pratiques pour optimiser vos index vectoriels et améliorer les résultats de vos requêtes.
Ajuster les options de la recherche vectorielle
La valeur optimale de la recherche vectorielle dépend du cas d'utilisation : le vecteur et sur les vecteurs de requête. Vous devrez peut-être effectuer un réglage itératif pour trouver les meilleures valeurs pour votre charge de travail spécifique.
Voici quelques consignes utiles à suivre lorsque vous choisissez des valeurs appropriées :
tree_depth
(niveau de l'arborescence) : si la table indexée comporte moins de 10 millions de lignes, utilisez2
commetree_depth
. Sinon, unetree_depth
de3
accepte des tables contenant jusqu'à 10 milliards de lignes.num_leaves
: utilise la racine carrée du nombre de lignes dans l'ensemble de données. Une valeur plus élevée peut augmenter le temps de création de l'index vectoriel. Évitez de définirnum_leaves
sur une valeur supérieure àtable_row_count/1000
, car cela entraîne des feuilles trop petites et de mauvaises performances.num_leaves_to_search
: cette option spécifie le nombre de nœuds de feuilles de l'index à rechercher. Augmenternum_leaves_to_search
améliore le rappel, mais aussi augmente la latence et les coûts. Nous vous recommandons d'utiliser un nombre représentant 1% du total nombre de feuilles défini dans l'instructionCREATE VECTOR INDEX
comme valeur pournum_leaves_to_search
. Si vous utilisez une clause de filtre, augmentez cette valeur pour élargir la recherche.
Si le rappel est acceptable, mais que le coût de l'interrogation est trop élevé,
ce qui entraîne un faible nombre maximal de RPS, essayez d'augmenter num_leaves
en suivant ces
étapes:
- Définissez
num_leaves
sur un multiple k de sa valeur d'origine (par exemple,2 * sqrt(table_row_count)
). - Définissez
num_leaves_to_search
de sorte qu'il soit identique à la valeur "k" de sa valeur d'origine. - Testez la réduction des
num_leaves_to_search
pour améliorer le coût et le nombre de RPS tout en maintenant le rappel.
Améliorer le rappel
Il existe plusieurs possibilités d'aggravation du rappel, dont les suivantes:
num_leaves_to_search
est trop petit: il peut s'avérer plus difficile de trouver les voisins les plus proches pour certains vecteurs de requête.num_leaves_to_search
pour rechercher plus de feuilles peut contribuer à améliorer le rappel. Récents les requêtes ont peut-être changé pour contenir davantage de ces vecteurs difficiles.L'index vectoriel doit être reconstruit : la structure arborescente de l'index vectoriel est optimisée pour l'ensemble de données au moment de sa création et devient statique par la suite. Par conséquent, si des vecteurs très différents sont ajoutés après la création de l'index vectoriel initial, la structure arborescente peut être sous-optimale, ce qui entraîne un rappel moins efficace.
Recompiler l'index vectoriel
Pour reconstruire votre index vectoriel sans temps d'arrêt:
- Créer un index vectoriel sur la même colonne de représentation vectorielle continue que le vecteur actuel
en mettant à jour les paramètres (par exemple,
OPTIONS
) le cas échéant. - Une fois l'index créé, modifiez l'indice
FORCE_INDEX
. à pointer vers le nouvel index pour mettre à jour la requête de recherche vectorielle. Cela garantit que la requête utilise le nouvel index vectoriel. (Vous devrez peut-être également réajusternum_leaves_to_search
dans votre nouvelle requête). - Supprimez l'index vectoriel obsolète.
Étape suivante
Apprenez-en plus sur les fonctions GoogleSQL
APPROXIMATE_COSINE_DISTANCE()
,APPROXIMATE_EUCLIDEAN_DISTANCE()
etAPPROXIMATE_DOT_PRODUCT()
.Apprenez-en davantage sur les instructions
VECTOR INDEX
GoogleSQL.