Cette page explique comment utiliser les embeddings stockés pour générer des index et interroger des embeddings à l'aide de l'index ScaNN
avec AlloyDB pour PostgreSQL.
Pour en savoir plus sur le stockage des embeddings, consultez Stocker des embeddings vectoriels.
AlloyDB alloydb_scann
est une extension PostgreSQL développée par Google qui implémente un index des voisins les plus proches très efficace basé sur l'algorithme ScaNN.
L'index ScaNN
est un index de quantification basé sur une arborescence pour la recherche approximative des plus proches voisins. Il permet de réduire le temps de création d'index et l'empreinte mémoire par rapport à HNSW
. De plus, il peut offrir un nombre de requêtes par seconde plus élevé que HNSW
en fonction de la charge de travail.
Avant de commencer
Avant de pouvoir commencer à créer des index, vous devez remplir les conditions préalables suivantes.
Les vecteurs d'embeddings sont ajoutés à une table de votre base de données AlloyDB.
L'extension
vector
basée surpgvector
, étendue par Google pour AlloyDB, et l'extensionalloydb_scann
sont installées :CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;
Si vous souhaitez créer des index ScaNN réglés automatiquement, assurez-vous que l'indicateur
scann.enable_preview_features
est activé. Si vous ne souhaitez pas activer les fonctionnalités en avant-première ou pour les instances de production, vous pouvez créer un index ScaNN avec des paramètres spécifiques.
Créer un index ScaNN réglé automatiquement
La fonctionnalité d'indexation automatique vous permet de simplifier la création d'index. Vous pouvez ainsi créer automatiquement des index optimisés pour les performances de recherche ou des index équilibrés en termes de temps de création et de performances de recherche.
Lorsque vous utilisez le mode AUTO
, il vous suffit de spécifier le nom de la table et de la colonne d'embedding, ainsi que la fonction de distance que vous souhaitez utiliser. Vous pouvez optimiser l'index pour les performances de recherche ou trouver un équilibre entre les temps de création de l'index et les performances de recherche.
Vous pouvez également utiliser le mode MANUAL
pour créer des index avec un contrôle précis sur d'autres paramètres d'optimisation des index.
Créer un index ScaNN en mode AUTO
Voici quelques points à noter avant de créer des index en mode AUTO
:
- AlloyDB ne peut pas créer d'index ScaNN pour les tables dont les données sont insuffisantes.
- Vous ne pouvez pas définir de paramètres de création d'index, tels que
num_leaves
, lorsque vous créez des index en modeAUTO
. - La maintenance automatique est activée par défaut pour tous les index créés en mode
AUTO
.
Pour créer un index en mode AUTO
, commencez par activer le flag de fonctionnalité scann.zero_knob_index_creation
.
Après avoir activé le flag, exécutez la commande suivante :
CREATE INDEX INDEX_NAME ON TABLE \
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) \
WITH (mode=AUTO', optimization='OPTIMIZATION');
Remplacez les éléments suivants :
INDEX_NAME
: nom de l'index que vous souhaitez créer, par exemplemy-scann-index
. Les noms d'index sont partagés dans toute votre base de données. Vérifiez que chaque nom d'index est unique pour chaque table de votre base de données.TABLE
: table à laquelle ajouter l'index.EMBEDDING_COLUMN
: colonne qui stocke les donnéesvector
.DISTANCE_FUNCTION
: fonction de distance à utiliser avec cet index. Choisissez l'une des options suivantes :Distance L2 :
l2
Produit scalaire :
dot_product
Distance de cosinus :
cosine
OPTIMIZATION
: définissez cette option sur l'une des valeurs suivantes :SEARCH_OPTIMIZED
: pour optimiser à la fois le rappel et la latence de la recherche vectorielle, au détriment d'un temps de création d'index plus long.BALANCED
: pour créer un index qui équilibre le temps de création de l'index et les performances de recherche.
Créer un index ScaNN
en mode MANUEL
Si vous avez activé l'indicateur scann.enable_preview_features
et que vous souhaitez contrôler précisément les paramètres d'optimisation, vous pouvez créer l'index en mode MANUAL
.
Pour créer un index ScaNN
en mode MANUAL
, exécutez la commande suivante :
CREATE INDEX INDEX_NAME ON TABLE \
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION) \
WITH (mode='MANUAL, num_leaves=NUM_LEAVES_VALUE, [quantizer =QUANTIZER, max_num_levels=MAX_NUM_LEVELS]);
Remplacez les éléments suivants :
INDEX_NAME
: nom de l'index que vous souhaitez créer, par exemplemy-scann-index
. Les noms d'index sont partagés dans toute votre base de données. Vérifiez que chaque nom d'index est unique pour chaque table de votre base de données.TABLE
: table à laquelle ajouter l'index.EMBEDDING_COLUMN
: colonne qui stocke les donnéesvector
.DISTANCE_FUNCTION
: fonction de distance à utiliser avec cet index. Choisissez l'une des options suivantes :Distance L2 :
l2
Produit scalaire :
dot_product
Distance de cosinus :
cosine
NUM_LEAVES_VALUE
: nombre de partitions à appliquer à cet index. Définissez une valeur comprise entre 1 et 1 048 576.QUANTIZER
: type de quantificateur à utiliser. Les options disponibles sont les suivantes :SQ8
: offre un équilibre entre les performances des requêtes et une perte de rappel minimale, généralement inférieure à 1 % ou 2 %. Il s'agit de la valeur par défaut.AH
: à envisager pour potentiellement améliorer les performances des requêtes lorsque le moteur en colonnes est activé et que les données de votre index et de votre table sont renseignées dans le moteur en colonnes, en fonction de sa taille configurée. Notez queAH
est compressé jusqu'à quatre fois par rapport àSQ8
. Pour en savoir plus, consultez Bonnes pratiques pour ajuster ScaNN.FLAT
: offre le rappel le plus élevé (99 % ou plus) au détriment des performances de recherche.
MAX_NUM_LEVELS
: nombre maximal de niveaux de l'arborescence de clustering en K-moyennes. Définissez la valeur sur1
(par défaut) pour la quantification arborescente à deux niveaux et sur2
pour la quantification arborescente à trois niveaux.
Vous pouvez ajouter d'autres paramètres d'exécution de requête ou de création d'index pour ajuster votre index. Pour en savoir plus, consultez Régler un index ScaNN
.
Modifier les modes pour les index existants
Si vous avez créé un index ScaNN en mode AUTO
et que vous souhaitez l'ajuster manuellement, vous devez passer au mode MANUAL
.
Pour passer au mode MANUAL
, procédez comme suit :
Mettez à jour l'index pour définir le mode sur
MANUAL
:ALTER INDEX INDEX_NAME SET (mode = 'MANUAL', num_leaves = NUM_LEAVES_VALUE);
Remplacez les éléments suivants :
INDEX_NAME
: nom de l'index que vous souhaitez créer, par exemplemy-scann-index
. Les noms d'index sont partagés dans toute votre base de données. Vérifiez que chaque nom d'index est unique pour chaque table de votre base de données.NUM_LEAVES_VALUE
: nombre de partitions à appliquer à cet index. Définissez une valeur comprise entre 1 et 1 048 576.
Vous pouvez ajouter d'autres paramètres d'exécution de requête ou de création d'index pour ajuster votre index. Pour en savoir plus, consultez Régler un index
ScaNN
.Recompilez votre index pour appliquer les paramètres :
REINDEX INDEX CONCURRENTLY INDEX_NAME;
Pour passer au mode AUTO
, procédez comme suit :
Mettez à jour l'index pour définir le mode sur
AUTO
:ALTER INDEX INDEX_NAME SET (mode = 'AUTO');
Recompilez votre index pour appliquer les paramètres :
REINDEX INDEX CONCURRENTLY INDEX_NAME;
Créer un index ScaNN
avec des paramètres spécifiques
Si votre application a des exigences spécifiques concernant le rappel et les temps de création d'index, vous pouvez créer l'index manuellement. Vous pouvez créer un index arborescent à deux ou trois niveaux en fonction de votre charge de travail. Pour en savoir plus sur le réglage des paramètres, consultez Régler un index ScaNN
.
Index arborescent à deux niveaux
Pour appliquer un index arborescent à deux niveaux à l'aide de l'algorithme ScaNN à une colonne contenant des embeddings vectoriels stockés, exécutez la requête LDD suivante :
CREATE INDEX INDEX_NAME ON TABLE
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (num_leaves=NUM_LEAVES_VALUE, quantizer =QUANTIZER);
Remplacez les éléments suivants :
INDEX_NAME
: nom de l'index que vous souhaitez créer, par exemplemy-scann-index
. Les noms d'index sont partagés dans toute votre base de données. Assurez-vous que chaque nom d'index est unique pour chaque table de votre base de données.TABLE
: table à laquelle ajouter l'index.EMBEDDING_COLUMN
: colonne qui stocke les donnéesvector
.DISTANCE_FUNCTION
: fonction de distance à utiliser avec cet index. Choisissez l'une des options suivantes :Distance L2 :
l2
Produit scalaire :
dot_product
Distance de cosinus :
cosine
NUM_LEAVES_VALUE
: nombre de partitions à appliquer à cet index. Définissez une valeur comprise entre 1 et 1 048 576. Pour savoir comment déterminer cette valeur, consultez Régler un indexScaNN
.QUANTIZER
: type de quantificateur à utiliser. Les options disponibles sont les suivantes :SQ8
: offre un équilibre entre les performances des requêtes et une perte de rappel minimale, généralement inférieure à 1 % ou 2 %. Il s'agit de la valeur par défaut.AH
: à envisager pour potentiellement améliorer les performances des requêtes lorsque le moteur en colonnes est activé et que les données de votre index et de votre table sont renseignées dans le moteur en colonnes, en fonction de sa taille configurée. Notez queAH
est compressé jusqu'à quatre fois par rapport àSQ8
. Pour en savoir plus, consultez Bonnes pratiques pour ajuster ScaNN.FLAT
: offre le rappel le plus élevé (99 % ou plus) au détriment des performances de recherche.
Index arborescent à trois niveaux
Pour créer un index arborescent à trois niveaux à l'aide de l'algorithme ScaNN dans une colonne contenant des embeddings vectoriels stockés, exécutez la requête LDD suivante :
CREATE INDEX INDEX_NAME ON TABLE
USING scann (EMBEDDING_COLUMN DISTANCE_FUNCTION)
WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = 2);
Une fois l'index créé, vous pouvez exécuter des requêtes de recherche des voisins les plus proches qui l'utilisent en suivant les instructions de la section Envoyer une requête de type plus proches voisins avec un texte donné.
Les paramètres d'index doivent être définis de manière à trouver le juste équilibre entre les requêtes par seconde et le rappel. Pour en savoir plus sur le réglage de l'index ScaNN
, consultez Régler un index ScaNN
.
Pour créer cet index sur une colonne d'embeddings qui utilise le type de données real[]
au lieu de vector
, convertissez le type de données de la colonne en vector
:
CREATE INDEX INDEX_NAME ON TABLE
USING scann (CAST(EMBEDDING_COLUMN AS vector(DIMENSIONS)) DISTANCE_FUNCTION)
WITH (num_leaves=NUM_LEAVES_VALUE, max_num_levels = MAX_NUM_LEVELS);
Remplacez DIMENSIONS
par la largeur dimensionnelle de la colonne d'embeddings. Pour savoir comment trouver les dimensions, examinez la fonction vector_dims
dans Fonctions vectorielles.
Pour obtenir une expérience de recherche cohérente, activez la maintenance automatique lorsque vous créez un index ScaNN. Pour en savoir plus, consultez Gérer les index vectoriels. Cette fonctionnalité est disponible en version preview.
Pour afficher la progression de l'indexation, utilisez la vue pg_stat_progress_create_index
:
SELECT * FROM pg_stat_progress_create_index;
La colonne phase
indique l'état actuel de la création de votre index. Une fois la phase de création de l'index terminée, la ligne correspondante n'est plus visible.
Pour régler votre index afin d'obtenir un équilibre entre le rappel et les RPS moyens, consultez Régler un index ScaNN
.
Créer des index en parallèle
Pour créer votre index plus rapidement, AlloyDB peut générer automatiquement plusieurs nœuds de calcul parallèles, en fonction de votre ensemble de données et du type d'index que vous choisissez.
La création d'index en parallèle est souvent déclenchée si vous créez un index ScaNN à trois niveaux ou si votre ensemble de données dépasse 100 millions de lignes.
Bien qu'AlloyDB optimise automatiquement le nombre de nœuds de calcul en parallèle, vous pouvez les ajuster à l'aide des paramètres de planification des requêtes PostgreSQL max_parallel_maintenance_workers
, max_parallel_workers
et min_parallel_table_scan_size
.
Exécuter une requête
Une fois que vous avez stocké et indexé les embeddings dans votre base de données, vous pouvez commencer à interroger vos données. Vous ne pouvez pas exécuter de requêtes de recherche groupées à l'aide de l'extension alloydb_scann
.
Pour trouver les voisins sémantiques les plus proches d'un vecteur d'embedding, vous pouvez exécuter l'exemple de requête suivant, dans lequel vous définissez la même fonction de distance que celle utilisée lors de la création de l'index.
SELECT * FROM TABLE
ORDER BY EMBEDDING_COLUMN DISTANCE_FUNCTION_QUERY ['EMBEDDING']
LIMIT ROW_COUNT
Remplacez les éléments suivants :
TABLE
: table contenant l'embedding auquel comparer le texte.INDEX_NAME
: nom de l'index que vous souhaitez utiliser (par exemple,my-scann-index
).EMBEDDING_COLUMN
: colonne contenant les embeddings stockés.DISTANCE_FUNCTION_QUERY
: fonction de distance à utiliser avec cette requête. Choisissez l'une des options suivantes, selon la fonction de distance utilisée lors de la création de l'index :Distance L2 :
<->
Produit interne :
<#>
Distance de cosinus :
<=>
EMBEDDING
: vecteur d'embedding pour lequel vous souhaitez trouver les plus proches voisins sémantiques qui sont stockés.ROW_COUNT
: nombre de lignes à afficher.Spécifiez
1
si vous souhaitez n'obtenir que la meilleure correspondance.
Vous pouvez également utiliser la fonction embedding()
pour traduire le texte en un vecteur. Comme embedding()
renvoie un tableau real
, vous devez convertir explicitement l'appel embedding()
en type de données vector
avant de l'appliquer à l'un des opérateurs de k-plus proches voisins (par exemple, <->
pour la distance L2). Ces opérateurs peuvent ensuite utiliser l'index ScaNN pour rechercher les lignes de la base de données présentant les embeddings les plus similaires sur le plan de la sémantique.
Étapes suivantes
- Exécuter des recherches de similarité vectorielle
- Régler les performances des requêtes vectorielles
- Métriques d'index vectoriel
- Découvrez comment créer un assistant d'achat intelligent avec AlloyDB, pgvector et la gestion des points de terminaison de modèle.