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

Impact sur les performances de la vue sur la fonction d'agrégation par rapport à la limitation de l'ensemble de résultats

Requêtes non strictement équivalentes

Pour clarifier le contexte :

  • max(id) exclut NULL valeurs. Mais ORDER BY ... LIMIT 1 pas.
  • NULL les valeurs sont triées en dernier dans l'ordre croissant et en premier dans l'ordre décroissant. Donc un Index Scan Backward peut ne pas trouver la plus grande valeur (selon max() ) d'abord, mais n'importe quel nombre de NULL valeurs.

L'équivalent formel de :

SELECT max(id) FROM testview;

n'est pas :

SELECT id FROM testview ORDER BY id DESC LIMIT 1;

mais :

SELECT id FROM testview ORDER BY id DESC NULLS LAST LIMIT 1;

Cette dernière requête n'obtient pas le plan de requête rapide. Mais ce serait le cas avec un index avec un ordre de tri correspondant :(id DESC NULLS LAST) .

C'est différent pour les fonctions d'agrégation min() et max() . Ceux-ci obtiennent un plan rapide lors du ciblage de la table test1 directement en utilisant l'index PK simple sur (id) . Mais pas lorsqu'il est basé sur la vue (ou directement sur la requête de jointure sous-jacente - la vue n'est pas le bloqueur). Un index triant les valeurs NULL au bon endroit n'a pratiquement aucun effet.

Nous sachez que id dans cette requête ne peut jamais être NULL . La colonne est définie NOT NULL . Et la jointure dans la vue est effectivement une INNER JOIN qui ne peut pas introduire NULL valeurs pour id .
Nous sachez aussi que l'index sur test.id ne peut pas contenir de valeurs NULL.
Mais le planificateur de requêtes Postgres n'est pas une IA. (Il n'essaie pas non plus de l'être, cela pourrait rapidement devenir incontrôlable.) Je vois deux lacunes :

  • min() et max() obtenir le plan rapide uniquement lors du ciblage de la table, quel que soit l'ordre de tri de l'index, une condition d'index est ajoutée :Index Cond: (id IS NOT NULL)
  • ORDER BY ... LIMIT 1 obtient le plan rapide uniquement avec l'ordre de tri de l'index correspondant exactement.

Je ne sais pas si cela pourrait être amélioré (facilement).

db<>violon ici - démontrant tout ce qui précède

Index

Cet index est complètement inutile :

CREATE INDEX ON "test" ("id");

Le PK sur test.id est implémenté avec un index unique sur la colonne, qui couvre déjà tout ce que l'index supplémentaire pourrait faire pour vous.

Il peut y en avoir d'autres, en attendant que la question soit éclaircie.

Cas de test déformé

Le cas de test est trop éloigné du cas d'utilisation réel pour être significatif.

Dans la configuration de test, chaque table a 100k lignes, il n'y a aucune garantie que chaque valeur dans joincol a une correspondance de l'autre côté, et les deux colonnes peuvent être NULL

Votre cas réel a 10 millions de lignes dans table1 et <100 lignes dans table2 , chaque valeur dans table1.joincol a une correspondance dans table2.joincol , les deux sont définis NOT NULL , et table2.joincol est unique. Une relation un-à-plusieurs classique. Il devrait y avoir un UNIQUE contrainte sur table2.joincol et une contrainte FK t1.joincol --> t2.joincol .

Mais c'est actuellement tout tordu dans la question. Attendre jusqu'à ce que ce soit nettoyé.