web-dev-qa-db-fra.com

Un index composite est-il également bon pour les requêtes sur le premier champ?

Disons que j'ai une table avec les champs A et B. Je fais des requêtes régulières sur A + B, j'ai donc créé un index composite sur (A,B). Les requêtes sur seulement A seraient-elles également entièrement optimisées par l'index composite?

De plus, j'ai créé un index sur A, mais Postgres utilise toujours l'index composite pour les requêtes sur seulement A. Si la réponse précédente est positive, je suppose que cela n'a pas vraiment d'importance, mais pourquoi sélectionne-t-il l'index composite par défaut, si l'index unique A est disponible?

93
Luciano

C'est certainement. Nous en avons discuté en détail sous cette question connexe:

L'espace est alloué en multiples de MAXALIGN, qui est généralement de 8 octets sur un système d'exploitation 64 bits ou (beaucoup moins commun) de 4 octets sur un système d'exploitation 32 bits. Si vous n'êtes pas sûr, vérifiez pg_controldata . Cela dépend également des types de données des colonnes indexées (certaines nécessitent un remplissage d'alignement) et du contenu réel.

Un index sur, disons, deux colonnes integer (4 octets chacune) finit généralement par être exactement aussi gros qu'un index sur un seul, où 4 autres octets sont perdus à cause du remplissage d'alignement.

Dans un tel cas, le planificateur de requêtes n'a vraiment aucun inconvénient à utiliser un index sur (a,b) - par rapport à un index sur seulement (a). Et il est généralement préférable que plusieurs requêtes utilisent le même index. La chance pour lui (ou des parties de celui-ci) de résider dans le cache (rapide) augmente lorsqu'il est partagé.

Si vous maintenez déjà un index sur (a,b), alors cela n'a pas de sens de créer un autre index juste sur (a) - sauf s'il est substantiellement plus petit. La même chose est pas true pour (b,a) contre. (a). Suivez le lien dans la première ligne pour en savoir plus.

Venant de la direction opposée, lorsque vous avez besoin d'un index supplémentaire comme celui sur (a,b), puis envisagez de supprimer un index existant uniquement sur (a) - si possible. Souvent impossible car c'est l'index d'une contrainte PK ou UNIQUE. Depuis Postgres 11, vous pourriez vous contenter d'ajouter simplement b à la définition de contrainte avec la clause INCLUDE à la place. Détails dans le manuel.

Ou créez le nouvel index sur (b,a) à la place pour couvrir les requêtes sur seulement b en plus. Pour les conditions d'égalité uniquement, l'ordre des expressions d'index dans les index btree n'a pas d'importance. Il le fait, cependant, lorsqu'il s'agit de conditions de plage. Voir:

Il y a des inconvénients potentiels à inclure des colonnes supplémentaires dans un index, même si cela n'utilise que de l'espace autrement perdu par le remplissage d'alignement:

  • Chaque fois que la colonne supplémentaire est mise à jour, l'index a également besoin d'une mise à jour, ce qui peut augmenter le coût des opérations d'écriture et créer plus de gonflement d'index.
  • Les mises à jour HOT (Heap Only Tuple) sur la table ne sont pas possibles tant que la colonne d'index any est impliquée.

Plus d'informations sur les mises à jour HOT:

Comment mesurer la taille des objets:

92
Erwin Brandstetter

Selon votre question, vous avez une table avec les champs A et B. Si votre requête est:

SELECT * FROM [YOUR TBL]
WHERE A='XXXX'

L'optimiseur choisira l'index composite pour éviter d'extraire l'accès aléatoire!

3
BongSey