La confusion autour de LEFT JOIN
et WHERE
clause a été clarifiée à plusieurs reprises :
Cette question intéressante reste :
Il n'y a pas d'indications de requête explicites dans Postgres. (Ce qui fait l'objet d'un débat en cours.) Mais il existe encore diverses astuces pour faire plier Postgres.
Mais d'abord, demandez-vous : Pourquoi le planificateur de requêtes a-t-il estimé que le plan choisi était moins cher au départ ? La configuration de votre serveur est-elle fondamentalement saine ? Paramètres de coût adéquats ? autovacuum
fonctionnement? La version de Postgres est obsolète ? Travaillez-vous autour d'un problème sous-jacent qui devrait vraiment être résolu ?
Si vous forcez Postgres à le faire à votre façon, vous devez être sûr qu'il ne se retournera pas, après une mise à niveau de version ou une mise à jour de la configuration du serveur... Vous feriez mieux de savoir exactement ce que vous faites.
Cela dit, vous pouvez forcer Postgres à "filtrer certains enregistrements avant de faire le JOIN
" avec une sous-requête où vous ajoutez OFFSET 0
- ce qui n'est que du bruit, logiquement, mais empêche Postgres de le réorganiser sous la forme d'une jointure régulière. (Indice de requête après tout)
SELECT la.listing_id, la.id, lar.*
FROM (
SELECT listing_id, id
FROM la
WHERE listing_id = 2780
OFFSET 0
) la
LEFT JOIN lar ON lar.application_id = la.id;
Ou vous pouvez utiliser un CTE (moins obscur, mais plus cher). Ou d'autres astuces comme la définition de certains paramètres de configuration. Ou, dans ce cas particulier, j'utiliserais un LATERAL
joindre dans le même sens :
SELECT la.listing_id, la.id, lar.*
FROM la
LEFT JOIN LATERAL (
SELECT *
FROM lar
WHERE application_id = la.id
) lar ON true
WHERE la.listing_id = 2780;
Connexe :
Voici un blog détaillé sur les conseils de requête par 2ndQuadrant. Cinq ans mais toujours valide.