Indexer la condition d'un index partiel dans Postgres

Sep 05 2020

J'essaie de raisonner sur la façon dont les index partiels de Postgres sont stockés dans Postgres. Supposons que je crée un index comme celui-ci

CREATE INDEX orders_unbilled_index ON orders (order_nr)
WHERE billed is not true

afin d'exécuter rapidement une requête comme

SELECT *
FROM orders
WHERE billed is not true AND order_nr > 1000000

Postgres stocke évidemment un index sur order_nrconstruit sur un sous-ensemble de la orderstable tel que défini par l'expression conditionnelle billed is not true. Cependant, j'ai quelques questions à ce sujet:

  1. Postgres stocke-t-il un autre index en interne billed is not truepour trouver rapidement les lignes associées à l'index partiel?
  2. Si (1) n'est pas le cas, est-ce que cela rendrait la requête ci-dessus plus rapide si je créais un index séparé sur billed is not true? (en supposant une grande table et quelques lignes avec billed is true)

EDIT: Mon exemple de requête basé sur les documents n'est pas le meilleur en raison de la façon dont les index booléens sont rarement utilisés , mais veuillez considérer mes questions dans le contexte de toute expression conditionnelle.

Réponses

2 LaurenzAlbe Sep 06 2020 at 12:08

Un index b-tree peut être considéré comme une liste ordonnée d'entrées d'index, chacune avec un pointeur vers une ligne de la table.

Dans un index partiel, la liste est juste plus petite: il n'y a que des entrées d'index pour les lignes qui remplissent la condition.

Si vous avez la condition d'index dans votre WHEREclause, PostgreSQL sait qu'il peut utiliser l'index et n'a pas à vérifier la condition d'index, car elle sera satisfaite automatiquement.

Alors:

  1. Non, toute ligne trouvée via l'index satisfera automatiquement à la condition d'index, donc l'utilisation de l'index suffit pour s'assurer qu'elle est satisfaite.

  2. Non, un index sur une colonne booléenne ne sera pas utilisé, car il ne serait pas moins cher que cet index partiel, et l'index partiel peut également être utilisé pour vérifier la condition order_nr.

    C'est en fait l'inverse: l'index partiel pourrait bien être utilisé pour les requêtes qui n'ont que la booleancolonne dans la WHEREcondition, s'il y a suffisamment de lignes qui satisfont à la condition.

TimBiegeleisen Sep 06 2020 at 04:39

Je crois comprendre que Postgres construira simplement un index qui ne peut être utilisé que pour rechercher des enregistrements qui ne sont billedpas vrais. Autrement dit, l'arbre B résultant serait indexé par le order_nr, mais ne renverrait à la table d'origine que s'il billedest faux.

Si vous continuez à lire la documentation , immédiatement après ce que vous avez cité, vous trouverez la requête suivante à titre d'exemple:

SELECT * FROM orders WHERE billed is not true AND amount > 5000.00;

Il est vrai que Postgres pourrait même choisir d'utiliser l'index défini sur la requête ci - dessus. Il peut utiliser votre index pour satisfaire cette requête en analysant l'intégralité de l'index. S'il y a un nombre relativement petit de commandes qui ne sont pas encore facturées, l'analyse de l'index order_nrpeut être préférable à une analyse complète de la table.

Donc, la réponse à votre question n ° 1 est que non, il n'y a pas d'index séparé pour billed, mais plutôt l'index sur order_nrne peut être utilisé que pour les enregistrements qui ont billedla valeur false. Et pour le n ° 2, oui, un deuxième index sur billed is not truepourrait être utilisé en supposant que peu d'enregistrements ne sont pas facturés. Cependant, même votre index actuel peut même être utilisé tel quel.