PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Spiegare più dettagliatamente il suggerimento sulle prestazioni della condizione JOIN vs. LEFT JOIN e WHERE

In effetti, WHERE condizioni e JOIN condizioni per [INNER] JOIN sono equivalenti al 100% in PostgreSQL. (È buona norma utilizzare JOIN esplicito condizioni per semplificare la lettura e la gestione delle query).

Lo stesso non true per un LEFT JOIN combinato con un WHERE condizione su una tabella a destra del join. Lo scopo di un LEFT JOIN è preservare tutte le righe sul lato sinistro del join, indipendentemente da una corrispondenza sul lato destro. Se non viene trovata alcuna corrispondenza, la riga viene estesa con NULL valori per le colonne sul lato destro. Il manuale:

LEFT OUTER JOIN

Innanzitutto, viene eseguito un inner join. Quindi, per ogni riga in T1 che non soddisfa la condizione di unione con nessuna riga in T2, viene aggiunta una riga unita con valori nulli nelle colonne di T2. Pertanto, la tabella unita ha sempre almeno una riga per ogni riga in T1.

Se poi applichi un WHERE condizione che richiede qualcosa di diverso da un NULL valore sulle colonne delle tabelle sul lato destro, annulli l'effetto e converti forzatamente il LEFT [OUTER] JOIN per funzionare come un semplice [INNER] JOIN , solo (forse) più costoso a causa di un piano di query più complicato.

In una query con molte tabelle unite, Postgres (o qualsiasi RDBMS) ha difficoltà a trovare il piano di query migliore (o anche buono). Il numero di sequenze teoricamente possibili per unire le tabelle cresce in modo fattoriale (!). Postgres utilizza "Generic Query Optimizer" per l'attività e ci sono alcune impostazioni per influenzarla.

Offuscare la query con LEFT JOIN fuorviante come indicato, rende più difficile il lavoro del pianificatore di query, è fuorviante per i lettori umani e in genere suggerisce errori nella logica della query.

Risposte correlate per problemi derivanti da questo:

  • Perché null è uguale a intero in WHERE?
  • Query con LEFT JOIN che non restituisce righe per il conteggio di 0
  • Query SQL utilizzando outer join e limitando i record figlio per ciascun genitore
  • Il join esterno sinistro si comporta come un join interno
  • Seleziona le righe che non sono presenti in un'altra tabella

ecc.