PostgreSQLLa base de données la plus sophistiquée au monde.
Documentation PostgreSQL 18 beta 1 » Langage SQL » Index » Index multicolonnes

11.3. Index multicolonnes #

Un index peut porter sur plusieurs colonnes d'une table. Soit, par exemple, une table de la forme :

CREATE TABLE test2 (
  majeur int,
  mineur int,
  nom varchar
);

(cas d'un utilisateur gardant son répertoire /dev dans une base de données...) et que des requêtes comme :

SELECT nom FROM test2 WHERE majeur = constante AND mineur = constante;

sont fréquemment exécutées. Il peut alors être souhaitable de définir un index qui porte sur les deux colonnes majeur et mineur. Ainsi :

CREATE INDEX test2_mm_idx ON test2 (majeur, mineur);

Actuellement, seuls les types d'index B-tree, GiST, GIN et BRIN supportent les index multicolonnes. Qu'il puisse y avoir plusieurs colonnes clés est indépendant de si les colonnes INCLUDE peuvent être ajoutées à l'index. Les index peuvent avoir jusqu'à 32 colonnes en incluant les colonnes INCLUDE. Cette limite peut être modifiée à la compilation de PostgreSQL. Voir le fichier pg_config_manual.h.

Un index B-tree multicolonne peut être utilisé avec des conditions de requêtes impliquant un sous-ensemble quelconque de colonnes de l'index. L'index est toutefois plus efficace lorsqu'il y a des contraintes sur les premières colonnes (celles de gauche). La règle exacte est la suivante : les contraintes d'égalité sur les premières colonnes, et toute contrainte d'inégalité sur la première colonne qui ne possède pas de contrainte d'égalité est utilisée pour limiter la partie parcourue de l'index. Les contraintes sur les colonnes à droite de ces colonnes sont vérifiées dans l'index donc elles éviteront toujours à perdre du temps à visiter la table, mais elles ne réduiront pas nécessairement la partie de l'index qui doit être visitée. Si un parcours d'index B-tree peut appliquer l'optimisation skip scan de manière efficace, il appliquera toutes les contraintes de colonne lors de la navigation au travers de l'index via des recherches répétées d'index. Ceci peut réduire la partie à lire de l'index, même si une ou plusieurs colonnes (avant la colonne d'index la moins significative pour le prédicat de la requête) manque une contrainte d'égalité standard. L'optimisation skip scan fonctionne en générant une contrainte interne d'égalité dynamique, qui correspond à toutes les valeurs possibles dans une colonne d'index (uniquement pour une colonne à qui il manque une contrainte d'égalité venant du prédicat de la requête, et seulement quand la contrainte générée peut être utilisée avec une constrainte de colonne ultérieure du prédicat de requête).

Par exemple, étant donné un index sur (x, y), et une condition de requête WHERE y = 7700, un parcours d'index B-tree pourrait être capable d'appliquer l'optimisation skip scan. Ceci survient généralement quand l'optimiseur de requête s'attend à ce que des recherches répétées de WHERE x = N AND y = 7700 pour chaque valeur possible de N (ou pour chaque valeur de x qui est réellement enregistrée dans l'index) soient l'approche la plus rapides, étant donné les index disponibles sur la table. Cette approche est généralement réalisée uniquement s'il y a peu de valeurs x au point que l'optimiseur s'attend à ce que le parcours ignore une majeure partie de l'index (parce que la plupart des blocs feuilles ne peut pas contenir les lignes intéressantes). S'il existe plus de valeurs x distinctes, alors l'index complet devra être parcouru, donc dans la plupart des cas, l'optimiseur préférera un parcours séquentiel de la table, plutôt que d'utiliser l'index.

L'optimisation skip scan peut aussi êre appliquée de façon sélective, lors des parcours de B-tree qui ont au moins quelques contraintes utiles provenant du prédicat de la requête.

Par exemple, avec un index sur (a, b, c) et une condition de requête WHERE a = 5 AND b >= 42 AND c < 77, l'index pourraît être parcouru de la première entrée avec a = 5 et b = 42 jusqu'à la dernière entrée avec a = 5. Les entrées d'index avec c >= 77 n'auront jamais besoin d'être filtrées au niveau de latable, mais il pourrait être profitable de les ignorer dans l'index. Lorsque l'optimisation skip scan est utilisée, le parcours commence une nouvelle recherche dans l'index à la fin du groupe a = 5 et b = N (c'est-à-dire de la position dans l'index où la première ligne a = 5 AND b = N AND c >= 77 apparaît), jusqu'au début du prochain groupe identique (c'est-à-dire la position dans l'index où la première ligne a = 5 AND b = N + 1 apparaît).

Un index GiST multicolonne peut être utilisé avec des conditions de requête qui impliquent un sous-ensemble quelconque de colonnes de l'index. Les conditions sur des colonnes supplémentaires restreignent les entrées renvoyées par l'index, mais la condition sur la première colonne est la plus importante pour déterminer la part de l'index parcourue. Un index GiST est relativement inefficace si sa première colonne n'a que quelques valeurs distinctes, même s'il y a beaucoup de valeurs distinctes dans les colonnes supplémentaires.

Un index multicolonne GIN peut être utilisé avec des conditions de requête qui impliquent tout sous-ensemble des colonnes de l'index. Contrairement à B-tree ou GiST, la qualité de la recherche dans l'index est identique quelles que soient les colonnes de l'index que la requête utilise.

Un index BRIN multicolonne peut être utilisé avec des conditions dans la requête qui impliquent tout sous-ensemble de colonnes dans l'index. Comme GIN et contrairement à B-tree ou GiST, l'efficacité de la recherche par l'index est la même quelles que soient les colonnes utilisées dans les conditions de la requête. La seule raison d'avoir plusieurs index BRIN au lieu d'un index BRIN multicolonne sur une table est d'avoir un paramétrage de stockage pages_per_range différent.

Chaque colonne doit évidemment être utilisée avec des opérateurs appropriés au type de l'index ; les clauses qui impliquent d'autres opérateurs ne sont pas prises en compte.

Il est préférable d'utiliser les index multicolonnes avec parcimonie. Dans la plupart des cas, un index sur une seule colonne est suffisant et préserve espace et temps. Les index de plus de trois colonnes risquent fort d'être inefficaces, sauf si l'utilisation de cette table est extrêmement stylisée. Voir aussi la Section 11.5 et Section 11.9 pour les discussions sur les mérites des différentes configurations d'index.