Zmatek kolem LEFT JOIN
a WHERE
klauzule byla mnohokrát objasněna:
Tato zajímavá otázka zůstává:
V Postgresu nejsou žádné explicitní tipy na dotazy. (Což je předmětem pokračujících debat.) Stále však existují různé triky, jak přimět Postgres, aby vám zahnul.
Nejdřív se však zeptejte sami sebe: Proč plánovač dotazů odhadl, že vybraný plán je pro začátek levnější? Je konfigurace vašeho serveru v zásadě rozumná? Je nastavení ceny dostatečné? autovacuum
běh? Verze Postgresu je zastaralá? Řešíte základní problém, který by měl být skutečně vyřešen?
Pokud přinutíte Postgres, aby to udělal po svém, měli byste si být jisti, že se po aktualizaci verze nebo aktualizaci konfigurace serveru znovu nespustí... Raději byste měli vědět, co přesně děláte.
To znamená, že můžete donutit Postgres, aby "odfiltroval některé záznamy před provedením JOIN
" s poddotazem, kam přidáte OFFSET 0
- což je logicky jen šum, ale brání Postgresu v jeho přeskupení do podoby běžného spojení. (Koneckonců nápověda k dotazu)
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;
Nebo můžete použít CTE (méně obskurní, ale dražší). Nebo jiné triky, jako je nastavení určitých konfiguračních parametrů. Nebo v tomto konkrétním případě použil bych LATERAL
spojit se stejným efektem:
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;
Související:
Zde je rozsáhlý blog o nápovědách k dotazům od 2ndQuadrant. Pět let staré, ale stále platné.