PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

PostgreSQL :Pourquoi cette requête n'utilise-t-elle pas mon index ?

Comme vous l'avez déjà compris, le problème est lié à l'utilisation d'opérateurs autres que les égaux. Un index ne peut être utilisé plus efficacement que pour les colonnes les plus à gauche qui sont comparées par des égaux (plus une condition de plage).

Dans votre exemple :

create index i on t (a,b,c,d);
where a=1 and b=11 and c!=5 and d<8;

Il ne peut utiliser l'index que pour a et b efficacement. Cela signifie que la base de données récupère toutes les lignes correspondant au a et b condition, puis vérifie chaque ligne par rapport aux conditions restantes.

Lorsque vous modifiez le filtre sur c égal à, il récupère (potentiellement) moins de lignes (uniquement celles correspondant à a et b et c ) puis vérifie ces (moins) lignes par rapport au d filtre. L'utilisation de l'index est plus efficace dans ce cas.

En général, le planificateur de requêtes PostgreSQL évalue les deux options :(1) en utilisant l'index; (2) faire un SeqScan. Pour les deux, il calcule une valeur de coût - plus elle est élevée, plus la performance attendue est mauvaise. Par conséquent, il prend celui dont la valeur de coût est la plus faible. C'est ainsi qu'il décide d'utiliser ou non l'index, il n'y a pas de seuil fixe.

Enfin, est écrit "plus une condition de gamme" ci-dessus. Cela signifie qu'il peut non seulement utiliser l'index de la manière la plus efficace si vous utilisez des signes égal, mais également pour une seule condition de plage.

Considérant que vous avez une seule condition de plage dans votre requête, je suggérerais de modifier l'index comme ceci :

create index i on t (a,b,d,c);

Maintenant, il peut utiliser les filtres sur a et b et d efficacement avec l'index et n'a besoin que de filtrer les lignes là où c!=5 . Bien que cet index puisse être utilisé plus efficacement pour votre requête que votre index d'origine, cela ne signifie pas automatiquement que PG l'utilisera. Cela dépend des estimations de coûts. Mais essayez-le.

Enfin, si ce n'est pas assez rapide et la valeur 5 vous utilisez dans l'expression c!=5 est constant, vous pouvez envisager un index partiel :

 create index i on t (a,b,d)
        where c!=5;

Vous pouvez également le faire avec toutes les autres colonnes, si les valeurs auxquelles vous les comparez sont des constantes.

Références :