Ce document vous explique comment ajuster vos index pour améliorer les performances des requêtes et le rappel.
Régler un index ScaNN
L'index ScaNN utilise l'indexation basée sur la quantification d'arbres. Dans les techniques de quantification arborescente, les index apprennent un arbre de recherche avec une fonction de quantification (ou de 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 est utilisée pour compresser la taille de l'index. Cette opération d'élagage accélère le calcul 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 taux de requêtes par seconde (RPS) élevé et un rappel élevé avec vos requêtes de voisins les plus proches, vous devez partitionner l'arborescence de votre index ScaNN
de la manière la plus approprié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 les indicateurs
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 rappel et 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 index. Le nombre de partitions que vous appliquez lors de la création d'un index a une incidence sur les performances de l'index. 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 se fait au détriment de la durée de création des index. Étant donné que les arbres à trois niveaux se construisent plus rapidement que ceux à deux niveaux, vous pouvez augmenter num_leaves_value lorsque vous créez un index d'arbre à trois niveaux pour améliorer les performances.
|
Création d'index |
quantizer |
Type de quantificateur à utiliser pour l'arbre 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 de la dimensionnalité utilisée pour réduire automatiquement la taille de l'embedding lorsque cela est possible. Cette option est activée par défaut. Définissez-la sur false si vous constatez une détérioration du rappel. |
Création d'index |
scann.num_leaves_to_search |
L'indicateur de base de données contrôle le compromis entre le rappel et les requêtes par seconde. La valeur par défaut est de 1 % de la valeur définie dans num_leaves . Plus la valeur définie est élevée, meilleur est le rappel, mais le nombre de requêtes par seconde est plus faible, et inversement. |
Durée d'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 un score ou en classant les voisins candidats analysés en mémoire au lieu du disque. La valeur par défaut est 20000 . Plus la valeur définie est élevée, plus le nombre de requêtes par seconde est élevé pour les requêtes filtrées, mais cela entraîne une utilisation plus importante de la mémoire, et inversement. |
Durée d'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 un nombre supérieur à celui des voisins que vous souhaitez que la requête renvoie. Des ensembles de valeurs plus élevés permettent d'obtenir un meilleur rappel, mais cette approche entraîne une diminution des RPS. |
Durée d'exécution de la requête |
max_num_levels |
Nombre maximal de niveaux de l'arbre de clustering K-means.
|
Création d'index |
Régler un index ScaNN
Considérez les exemples suivants pour les index ScaNN
à deux et trois niveaux qui montrent comment les paramètres d'optimisation 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 index 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 du rappel.
Vous pouvez surveiller les métriques d'index pour déterminer le nombre de mutations créées depuis la création de l'index, puis le réindexer en conséquence. Pour en savoir plus sur les métriques, consultez Métriques d'index vectoriel.
Bonnes pratiques pour l'optimisation
Les recommandations pour optimiser votre index varient en fonction du type d'index ScaNN
que vous prévoyez d'utiliser. Cette section fournit des recommandations sur la façon d'ajuster les paramètres d'index pour obtenir un équilibre optimal entre le rappel et les requêtes par seconde.
Index arborescent à deux niveaux
Pour appliquer des recommandations qui vous aideront à 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'à ce que vous atteigniez 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 de l'ensemble de données qui vous aidera à atteindre le rappel cible.
Si vous travaillez avec des vecteurs de grande dimension (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
en suivant les conseils ci-dessous :- Définissez
num_leaves
sur un facteur plus élevé de la racine carrée du nombre de lignes. Par exemple, si l'index est défini surnum_leaves
pour la racine carrée du nombre de lignes, essayez de le définir sur le double de la racine carrée. Si la valeur est déjà double, 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.
Pendant que vous exécutez les requêtes de test, essayez de réduire
scann.num_leaves_to_search
pour trouver une valeur qui augmente le RPS tout en conservant 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 RPS et la plage de rappel aient atteint des valeurs acceptables.
Index arborescent à trois niveaux
En plus des recommandations pour l'index d'arborescence à deux niveaux ScaNN
, suivez les conseils et les étapes ci-dessous pour ajuster l'index :
- L'augmentation de
max_num_levels
de1
pour un arbre à deux niveaux à2
pour un arbre à trois niveaux réduit considérablement le temps nécessaire à la création d'un index, mais au détriment de la précision du rappel. Définissezmax_num_levels
en suivant la recommandation ci-dessous :- Définissez la valeur sur
2
si le nombre de lignes de vecteur dépasse 100 millions. - Définissez la valeur sur
1
si le nombre de lignes de vecteur est inférieur à 10 millions. - Définissez la valeur sur
1
ou2
si le nombre de lignes de vecteur est compris entre 10 millions et 100 millions, en fonction de l'équilibre entre le temps de création de l'index et la précision du 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 vecteur supérieures à 100 millions de lignes : définissez
max_num_levels
sur2
etnum_leaves
surpower(rows, ⅔)
. - Moins de 100 millions de lignes de vecteurs : définissez
max_num_levels
sur1
etnum_leaves
sursqrt(rows)
. - Lignes de vecteur comprises entre 10 millions et 100 millions : commencez par définir
max_num_levels
sur1
etnum_leaves
sursqrt(rows)
.
- Lignes de vecteur supérieures à 100 millions de lignes : 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 obtenir une précision de rappel optimale.Si vous n'êtes pas satisfait du temps de création de l'index, procédez comme suit :
Si la valeur
max_num_levels
est1
, supprimez l'index. Reconstruisez l'index en définissant la valeurmax_num_levels
sur2
.Exécutez les requêtes et ajustez la valeur
num_leaves
pour une précision de rappel optimale.Si la valeur
max_num_levels
est2
, supprimez l'index. Reconstruisez l'index avec la même valeurmax_num_levels
et ajustez la valeurnum_leaves
pour 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. Le point 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 quantificateur à utiliser pour l'arbre 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 |
Nombre de listes les plus proches à explorer lors de la recherche. La valeur de départ est sqrt(lists) . |
Durée d'exécution de la requête |
Prenons l'exemple suivant, qui montre un index IVF
avec les paramètres d'optimisation 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. Le point 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. La valeur de départ est sqrt(lists) . |
Durée d'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 de l'index sur les grandes tables.
Prenons l'exemple suivant, qui montre un index IVFFlat
avec les paramètres d'optimisation 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 à partir d'un nœud du graphique. Vous pouvez commencer par la valeur par défaut 16 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 dynamique de candidats conservée 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 au double de la valeur m (par exemple, 64 , qui est la valeur 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 tout en observant le rappel. La valeur par défaut est 40 . |
Durée d'exécution de la requête |
Prenons l'exemple suivant, qui montre un index hnsw
avec les paramètres d'optimisation 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 indiqué 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 écoulé, le nombre de lignes analysées ou renvoyées, et 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 d'index vectoriel
Vous pouvez utiliser les métriques d'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 d'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 Métriques d'index vectoriel.