ORDER BY
Au delà du simple fait de trouver les lignes à renvoyer à une requête, un index
peut les renvoyer dans un ordre spécifique. Cela permet de résoudre une
clause ORDER BY
sans
étape de tri séparée. De tous les types d'index actuellement supportés par
PostgreSQL, seuls les B-tree peuvent produire une
sortie triée -- les autres types d'index renvoient les lignes
correspondantes dans un ordre imprécis, dépendant de l'implantation.
Le planificateur répond à une clause ORDER BY
soit en parcourant un index disponible qui correspond à la
clause, soit en parcourant la table dans l'ordre physique et en réalisant
un tri explicite. Pour une requête qui nécessite de parcourir une fraction
importante de la table, le tri explicite est probablement plus rapide que
le parcours d'un index car il nécessite moins d'entrées/sorties disque, du
fait de son accès séquentiel. Les index sont plus utiles lorsqu'il s'agit
de ne récupérer que
quelques lignes être récupérées. ORDER BY
combiné à LIMIT
n
est un cas
spécial très important :
un tri explicite doit traiter toutes les données pour identifier les
n
première lignes, mais s'il y a un index
qui correspond à l'ORDER BY
, alors les
n
premières lignes peuvent être récupérées directement
sans qu'il soit nécessaires de parcourir les autres.
Par défaut, les index B-tree stockent leurs entrées dans l'ordre ascendant,
valeurs NULL en dernier. Cela signifie que le parcours avant
d'un index sur une colonne x
produit une sortie
satisfaisant ORDER BY x
(ou en plus verbeux
ORDER BY x ASC NULLS LAST
). L'index peut aussi être
parcouru en arrière, produisant ainsi une sortie satisfaisant un
ORDER BY x DESC
(ou en plus verbeux
ORDER BY x DESC NULLS FIRST
car
NULLS FIRST
est la valeur par défaut pour un
ORDER BY DESC
).
L'ordre d'un index B-tree peut être défini à la création par l'inclusion des options
ASC
, DESC
, NULLS FIRST
,
et/ou NULLS LAST
lors de la création de l'index ; par
exemple :
CREATE INDEX test2_info_nulls_low ON test2 (info NULLS FIRST); CREATE INDEX test3_desc_index ON test3 (id DESC NULLS LAST);
Un index stocké en ordre ascendant avec les valeurs NULL en premier peut
satisfaire soit ORDER BY x ASC NULLS FIRST
soit
ORDER BY x DESC NULLS LAST
selon la direction du
parcours.
On peut s'interroger sur l'intérêt de proposer quatre options, alors que
deux options associées à la possibilité d'un parcours inverse semblent
suffire à couvrir toutes les
variantes d'ORDER BY
. Dans les index mono-colonne,
les options sont en effet redondantes, mais pour un index à plusieurs colonnes,
elles sont utiles. Si l'on considère un index à deux colonnes
(x, y)
, il peut satisfaire une clause ORDER
BY x, y
sur un parcours avant, ou
ORDER BY x DESC, y DESC
sur un parcours inverse.
Mais il se peut que l'application utilise fréquemment
ORDER BY x ASC, y DESC
. Il n'y a pas moyen d'obtenir cet
ordre à partir d'un index plus simple, mais c'est possible si l'index est défini
comme (x ASC, y DESC)
or (x DESC, y
ASC)
.
Les index d'ordre différent de celui par défaut sont visiblement une fonctionnalité très spécialisée, mais ils peuvent parfois être à l'origine d'accélérations spectaculaires des performances sur certaines requêtes. L'intérêt de maintenir un tel index dépend de la fréquence des requêtes qui nécessitent un tri particulier.