Ce document explique comment optimiser vos index pour améliorer les performances des requêtes et la récupération.
Régler un indice ScaNN
L'index ScaNN utilise une indexation basée sur la quantification arborescente. Dans les techniques de quantification arborescente, les index apprennent un arbre de recherche avec une fonction de quantification (ou hachage). Lorsque vous exécutez une requête, l'arborescence de recherche est utilisée pour élaguer l'espace de recherche, tandis que la quantification permet de compresser la taille de l'index. Cette élagage accélère l'évaluation de la similarité (c'est-à-dire de la distance) entre le vecteur de requête et les vecteurs de la base de données.
Pour obtenir à la fois un nombre élevé de requêtes par seconde (RPS) et un rappel élevé avec vos requêtes de voisin le plus proche, vous devez partitionner l'arborescence de votre index ScaNN
de la manière la plus adaptée à vos données et à vos requêtes.
Avant de créer un index ScaNN
, procédez comme suit:
- Assurez-vous qu'une table contenant vos données a déjà été créée.
- Assurez-vous que la valeur que vous définissez pour l'indicateur
maintenance_work_mem
etshared_buffers
est inférieure à la mémoire totale de la machine pour éviter les problèmes lors de la génération de l'index.
Paramètres de réglage
Les paramètres d'index et les indicateurs de base de données suivants sont utilisés ensemble pour trouver le bon équilibre entre le rappel et le RPS. Tous les paramètres s'appliquent aux deux types d'index ScaNN
.
Paramètre de réglage | Description | Type de paramètre |
---|---|---|
num_leaves |
Nombre de partitions à appliquer à cet indice. Le nombre de partitions auxquelles vous appliquez un index lors de sa création affecte ses performances. En augmentant le nombre de partitions pour un nombre défini de vecteurs, vous créez un index plus précis, ce qui améliore le rappel et les performances des requêtes. Toutefois, cela entraîne des temps de création d'index plus longs. Étant donné que les arbres à trois niveaux sont créés plus rapidement que les arbres à deux niveaux, vous pouvez augmenter la valeur num_leaves_value lorsque vous créez un indice d'arbre à trois niveaux pour obtenir de meilleures performances.
|
Création d'index |
quantizer |
Type de quantizeur que vous souhaitez utiliser pour l'arborescence k-means. La valeur par défaut est SQ8 pour améliorer les performances des requêtes.Définissez-la sur FLAT pour améliorer le rappel. |
Création d'index |
enable_pca |
Active l'analyse des composants principaux (ACP), une technique de réduction des dimensions utilisée pour réduire automatiquement la taille de l'encapsulation lorsque cela est possible. Cette option est activée par défaut. Définir sur false si vous constatez une dégradation de la mémorisation. |
Création d'index |
scann.num_leaves_to_search |
L'indicateur de base de données contrôle le compromis entre le rappel et le RPS. La valeur par défaut est de 1% de la valeur définie dans num_leaves . Plus la valeur définie est élevée, plus le rappel est élevé, mais le RPS est plus faible, et inversement. |
Exécution de la requête |
scann.max_top_neighbors_buffer_size |
L'indicateur de base de données spécifie la taille du cache utilisé pour améliorer les performances des requêtes filtrées en attribuant une note ou un classement aux voisins candidats analysés en mémoire plutôt que sur le disque. La valeur par défaut est 20000 . Plus la valeur définie est élevée, plus le RPS est élevé pour les requêtes filtrées, mais cela entraîne une utilisation plus importante de la mémoire. À l'inverse, plus la valeur est faible, moins le débit de requêtes par seconde est élevé. |
Exécution de la requête |
scann.pre_reordering_num_neighbors |
Lorsque l'indicateur de base de données est défini, il spécifie le nombre de voisins candidats à prendre en compte lors des étapes de réorganisation après que la recherche initiale a identifié un ensemble de candidats. Définissez cette valeur sur une valeur supérieure au nombre de voisins que vous souhaitez que la requête renvoie. Des ensembles de valeurs plus élevées améliorent le rappel, mais cette approche réduit le RPS. |
Exécution de la requête |
max_num_levels |
Nombre maximal de niveaux de l'arbre de partitionnement en k-moyennes.
|
Création d'index |
Régler un indice ScaNN
Prenons les exemples suivants d'index ScaNN
à deux et trois niveaux qui montrent comment les paramètres de réglage sont définis:
Index à deux niveaux
SET LOCAL scann.num_leaves_to_search = 1;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 1/2)]);
Index à trois niveaux
SET LOCAL scann.num_leaves_to_search = 10;
SET LOCAL scann.pre_reordering_num_neighbors=50;
CREATE INDEX my-scann-index ON my-table
USING scann (vector_column cosine)
WITH (num_leaves = [power(1000000, 2/3)], max_num_levels = 2);
Toute opération d'insertion ou de mise à jour sur une table pour laquelle un indice ScaNN
est déjà généré a un impact sur la façon dont l'arbre appris optimise l'index. Si votre table est sujette à des mises à jour ou des insertions fréquentes, nous vous recommandons de réindexer régulièrement l'index ScaNN
existant pour améliorer la précision de la récupération.
Vous pouvez surveiller les métriques de l'index pour déterminer le nombre de mutations créées depuis la création de l'index, puis réindexer en conséquence. Pour en savoir plus sur les métriques, consultez la section Métriques de l'index vectoriel.
Bonnes pratiques de réglage
Les recommandations de réglage de l'index varient selon le type d'index ScaNN
que vous prévoyez d'utiliser. Cette section fournit des recommandations sur l'ajustement des paramètres d'index pour obtenir un équilibre optimal entre le rappel et le RPS.
Index arborescent à deux niveaux
Pour appliquer des recommandations afin de vous aider à trouver les valeurs optimales de num_leaves
et num_leaves_to_search
pour votre ensemble de données, procédez comme suit:
- Créez l'index
ScaNN
avecnum_leaves
défini sur la racine carrée du nombre de lignes de la table indexée. - Exécutez vos requêtes de test, en augmentant la valeur de
scann.num_of_leaves_to_search
, jusqu'à atteindre la plage de rappel cible (par exemple, 95 %). Pour en savoir plus sur l'analyse de vos requêtes, consultez Analyser vos requêtes. - Notez le ratio entre
scann.num_leaves_to_search
etnum_leaves
qui sera utilisé dans les étapes suivantes. Ce ratio fournit une approximation autour de l'ensemble de données qui vous aidera à atteindre votre rappel cible.
Si vous travaillez avec des vecteurs à dimension élevée (500 dimensions ou plus) et que vous souhaitez améliorer le rappel, essayez d'ajuster la valeur descann.pre_reordering_num_neighbors
. Pour commencer, définissez la valeur sur100 * sqrt(K)
, oùK
correspond à la limite que vous avez définie dans votre requête. - Si votre RPS est trop faible une fois que vos requêtes ont atteint un rappel cible, procédez comme suit :
- Recréez l'index en augmentant la valeur de
num_leaves
etscann.num_leaves_to_search
conformément aux instructions suivantes :- Définissez
num_leaves
sur un facteur plus élevé de la racine carrée du nombre de lignes. Par exemple, sinum_leaves
est défini sur la racine carrée du nombre de lignes de l'index, essayez de le définir sur le double de la racine carrée. Si la valeur est déjà doublée, essayez de la définir sur le triple de la racine carrée. - Augmentez
scann.num_leaves_to_search
si nécessaire pour maintenir son ratio avecnum_leaves
, que vous avez noté à l'étape 3. - Définissez
num_leaves
sur une valeur inférieure ou égale au nombre de lignes divisé par 100.
- Définissez
- Exécutez à nouveau les requêtes de test.
Lorsque vous exécutez les requêtes de test, essayez de réduire
scann.num_leaves_to_search
afin de trouver une valeur qui augmente le RPS tout en maintenant un taux de rappel élevé. Essayez différentes valeurs descann.num_leaves_to_search
sans reconstruire l'index.
- Recréez l'index en augmentant la valeur de
- Répétez l'étape 4 jusqu'à ce que la plage de RPS et le débit de requêtes par seconde atteignent des valeurs acceptables.
Index arborescent à trois niveaux
En plus des recommandations concernant l'index ScaNN
en arbre à deux niveaux, suivez les conseils ci-dessous et la procédure d'ajustement de l'index:
- Augmenter la valeur de
max_num_levels
de1
pour un arbre à deux niveaux à2
pour un arbre à trois niveaux réduit considérablement le temps de création d'un indice, mais au détriment de la précision du rappel. Définissezmax_num_levels
à l'aide de la recommandation suivante :- Définissez la valeur sur
2
si le nombre de lignes vectorielles dépasse 100 millions. - Définissez la valeur sur
1
si le nombre de lignes vectorielles est inférieur à 10 millions. - Définissez la valeur sur
1
ou2
si le nombre de lignes de vecteurs est compris entre 10 et 100 millions, en fonction du temps de création de l'index et de la précision de rappel dont vous avez besoin.
- Définissez la valeur sur
Pour appliquer des recommandations afin de trouver la valeur optimale des paramètres d'index num_leaves
et max_num_levels
, procédez comme suit:
Créez l'index
ScaNN
avec les combinaisonsnum_leaves
etmax_num_levels
suivantes en fonction de votre ensemble de données:- Lignes de vecteurs supérieures à 100 millions: définissez
max_num_levels
sur2
etnum_leaves
surpower(rows, ⅔)
. - Lignes vectorielles inférieures à 100 millions: définissez
max_num_levels
sur1
etnum_leaves
sursqrt(rows)
. - Lignes de vecteurs comprises entre 10 et 100 millions de lignes: commencez par définir
max_num_levels
sur1
etnum_leaves
sursqrt(rows)
.
- Lignes de vecteurs supérieures à 100 millions: définissez
Exécutez vos requêtes de test. Pour en savoir plus sur l'analyse des requêtes, consultez Analyser vos requêtes.
Si le temps de création de l'index est satisfaisant, conservez la valeur
max_num_levels
et testez la valeurnum_leaves
pour une précision de rappel optimale.Si vous n'êtes pas satisfait du délai de création de l'index, procédez comme suit:
Si la valeur
max_num_levels
est1
, supprimez l'index. Recréez l'index en définissant la valeurmax_num_levels
sur2
.Exécutez les requêtes et ajustez la valeur
num_leaves
pour obtenir une précision de rappel optimale.Si la valeur
max_num_levels
est2
, supprimez l'index. Recréez l'index avec la même valeurmax_num_levels
et ajustez la valeurnum_leaves
pour obtenir une précision de rappel optimale.
Régler un index IVF
Ajuster les valeurs que vous définissez pour les paramètres lists
, ivf.probes
et quantizer
peut vous aider à optimiser les performances de votre application:
Paramètre de réglage | Description | Type de paramètre |
---|---|---|
lists |
Nombre de listes créées lors de la création de l'index. La valeur de départ pour définir cette valeur est (rows)/1000 pour un maximum d'un million de lignes et sqrt(rows) pour plus d'un million de lignes. |
Création d'index |
quantizer |
Type de quantizeur que vous souhaitez utiliser pour l'arborescence k-means. La valeur par défaut est SQ8 pour améliorer les performances des requêtes. Définissez-le sur FLAT pour améliorer le souvenir. |
Création d'index |
ivf.probes |
le nombre de listes les plus proches à explorer lors de la recherche. Le point de départ de cette valeur est sqrt(lists) . |
Exécution de la requête |
Prenons l'exemple suivant, qui montre un indice IVF
avec les paramètres de réglage définis:
SET LOCAL ivf.probes = 10;
CREATE INDEX my-ivf-index ON my-table
USING ivf (vector_column cosine)
WITH (lists = 100, quantizer = 'SQ8');
Régler un index IVFFlat
Ajuster les valeurs que vous définissez pour les paramètres lists
et ivfflat.probes
peut vous aider à optimiser les performances de l'application:
Paramètre de réglage | Description | Type de paramètre |
---|---|---|
lists |
Nombre de listes créées lors de la création de l'index. La valeur de départ pour définir cette valeur est (rows)/1000 pour un maximum d'un million de lignes et sqrt(rows) pour plus d'un million de lignes. |
Création d'index |
ivfflat.probes |
Nombre de listes les plus proches à explorer lors de la recherche. Le point de départ de cette valeur est sqrt(lists) . |
Exécution de la requête |
Avant de créer un index IVFFlat
, assurez-vous que l'indicateur max_parallel_maintenance_workers
de votre base de données est défini sur une valeur suffisante pour accélérer la création d'index sur de grandes tables.
Prenons l'exemple suivant, qui montre un indice IVFFlat
avec les paramètres de réglage définis:
SET LOCAL ivfflat.probes = 10;
CREATE INDEX my-ivfflat-index ON my-table
USING ivfflat (vector_column cosine)
WITH (lists = 100);
Régler un index HNSW
Ajuster les valeurs que vous définissez pour les paramètres m
, ef_construction
et hnsw.ef_search
peut vous aider à optimiser les performances de l'application.
Paramètre de réglage | Description | Type de paramètre |
---|---|---|
m |
Nombre maximal de connexions par nœud du graphique. Vous pouvez commencer avec la valeur par défaut 16 (par défaut) et tester des valeurs plus élevées en fonction de la taille de votre ensemble de données. |
Création d'index |
ef_construction |
Taille de la liste des candidats dynamiques maintenue lors de la construction du graphique, qui met constamment à jour les meilleurs candidats actuels pour les voisins les plus proches d'un nœud. Définissez cette valeur sur une valeur supérieure à deux fois la valeur m (par exemple, 64 par défaut). |
Création d'index |
ef_search |
Taille de la liste de candidats dynamiques utilisée lors de la recherche. Vous pouvez commencer par définir cette valeur sur m ou ef_construction , puis la modifier en observant le rappel. La valeur par défaut est 40 . |
Exécution de la requête |
Prenons l'exemple suivant, qui montre un indice hnsw
avec les paramètres de réglage définis:
SET LOCAL hnsw.ef_search = 40;
CREATE INDEX my-hnsw-index ON my-table
USING hnsw (vector_column cosine)
WITH (m = 16, ef_construction = 200);
Analyser vos requêtes
Utilisez la commande EXPLAIN ANALYZE
pour analyser vos insights sur les requêtes, comme illustré dans l'exemple de requête SQL suivant.
EXPLAIN ANALYZE SELECT result-column FROM my-table
ORDER BY EMBEDDING_COLUMN ::vector
USING INDEX my-scann-index
<-> embedding('textembedding-gecko@003', 'What is a database?')
LIMIT 1;
L'exemple de réponse QUERY PLAN
inclut des informations telles que le temps passé, le nombre de lignes analysées ou renvoyées, ainsi que les ressources utilisées.
Limit (cost=0.42..15.27 rows=1 width=32) (actual time=0.106..0.132 rows=1 loops=1)
-> Index Scan using my-scann-index on my-table (cost=0.42..858027.93 rows=100000 width=32) (actual time=0.105..0.129 rows=1 loops=1)
Order By: (embedding_column <-> embedding('textgecko@003', 'What is a database?')::vector(768))
Limit value: 1
Planning Time: 0.354 ms
Execution Time: 0.141 ms
Afficher les métriques de l'index vectoriel
Vous pouvez utiliser les métriques de l'index vectoriel pour examiner les performances de votre index vectoriel, identifier les points à améliorer et ajuster votre index en fonction des métriques, si nécessaire.
Pour afficher toutes les métriques de l'index vectoriel, exécutez la requête SQL suivante, qui utilise la vue pg_stat_ann_indexes
:
SELECT * FROM pg_stat_ann_indexes;
Pour obtenir la liste complète des métriques, consultez la section Métriques de l'index vectoriel.