sql >> Databáze >  >> RDS >> PostgreSQL

Vysvětlete podrobněji návrh výkonu JOIN vs. LEFT JOIN a WHERE

Efektivně WHERE podmínky a JOIN podmínky pro [INNER] JOIN jsou 100% ekvivalentní v PostgreSQL. (Dobrým postupem je používat explicitní JOIN podmínky pro usnadnění čtení a údržby dotazů).

Totéž ne true pro LEFT JOIN v kombinaci s WHERE stav na stole napravo od spojení. Účel LEFT JOIN je zachovat všechny řádky na levé straně spojení, bez ohledu na shodu na pravé straně. Pokud není nalezena žádná shoda, řádek se rozšíří o NULL hodnoty pro sloupce na pravé straně. Manuál:

LEFT OUTER JOIN

Nejprve se provede vnitřní spojení. Potom se pro každý řádek v T1, který nesplňuje podmínku spojení s žádným řádkem v T2, přidá spojený řádek s hodnotami null ve sloupcích T2. Spojená tabulka má tedy vždy alespoň jeden řádek pro každý řádek v T1.

Pokud poté použijete WHERE stav, který vyžaduje něco jiného než NULL hodnotu ve sloupcích tabulek na pravé straně, zrušíte efekt a vynuceně převedete LEFT [OUTER] JOIN fungovat jako obyčejný [INNER] JOIN , jen (možná) dražší kvůli složitějšímu plánu dotazů.

V dotazu s mnoha spojenými tabulkami je pro Postgres (nebo jakýkoli RDBMS) těžké najít nejlepší (nebo dokonce dobrý) plán dotazů. Počet teoreticky možných sekvencí ke spojení tabulek faktoricky roste (!). Postgres pro tento úkol používá "Generic Query Optimizer" a existují určitá nastavení, která to ovlivňují.

Zatemnění dotazu zavádějícím LEFT JOIN jak je uvedeno, ztěžuje práci plánovače dotazů, je pro lidské čtenáře zavádějící a obvykle naznačuje chyby v logice dotazu.

Související odpovědi na problémy vyplývající z tohoto:

  • Proč se null rovná celému číslu ve WHERE?
  • Dotaz s LEFT JOIN nevrací řádky pro počet 0
  • Dotaz SQL pomocí vnějšího spojení a omezení podřízených záznamů pro každého rodiče
  • Levé vnější spojení funguje jako vnitřní spojení
  • Vyberte řádky, které se nenacházejí v jiné tabulce

atd.



  1. Použití docker-compose k vytvoření tabulek v databázi postgresql

  2. Pokuste se znovu otevřít již uzavřený objekt sqlitedatabase

  3. Použití funkce Max() k výběru skupinových hodnot

  4. Nelze se připojit k serveru MySQL na 'localhost' (10061)