Inner join vs Where


257

C'è una differenza nelle prestazioni (in oracolo) tra

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

E

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?


1
solo per la cronaca, ho visto che le query restituiscono risultati diversi solo cambiando da un join a una clausola
where

12
@BlackTigerX: risultati diversi? Ci sono stati dei join esterni coinvolti? Perché non vedo come potrebbero verificarsi risultati diversi tra un inner join ... onversus e l'inserimento di criteri di join equivalenti nella whereclausola.
Shannon Severance

nella vecchia versione del database Oracle non esistejoin
Majid Taheri,

2
@MajidTaheri: di quanti anni parla di una versione di Oracle? Qualsiasi versione supportata da Oracle supporta la notazione JOIN.
Jonathan Leffler,

Cerca le risposte generali o le migliori pratiche basate su casi insignificanti. Vorrei vedere un "re-match" con clausole dove più complesse che coinvolgono più condizioni AND. Almeno con SQL Server c'è un punto di crossover.
crokusek,

Risposte:


195

No! Lo stesso piano di esecuzione, guarda queste due tabelle:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

Il piano di esecuzione per la query utilizzando il join interno:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

E il piano di esecuzione per la query utilizzando una clausola WHERE.

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

4
Vorrei davvero vedere se ci sono documenti ufficiali di Oracle che ne parlano
4 Lascia il

68

Se Query Optimizer sta eseguendo correttamente il proprio lavoro, non dovrebbero esserci differenze tra queste query. Sono solo due modi per specificare lo stesso risultato desiderato.


22
Sì, le prestazioni dovrebbero essere le stesse. Ma la sintassi SELECT * FROM Table1, Table2 WHERE ... è MALE!
Joel Coehoorn,

2
Trovo molto più facile comprendere FOR INNER JOINS rispetto alla sintassi SQL-92. Il tuo chilometraggio può variare.
Craig Trader,

25
Trovo che la sintassi WHERE sia più facile da leggere di INNER JION - immagino sia come Vegemite. Molte persone nel mondo probabilmente lo trovano disgustoso, ma i bambini cresciuti mangiandolo lo adorano.
ScottCher,

3
Vegemite è davvero brutto, ma poi di nuovo amo scrapple. Vai a capire.
StingyJack,

2
@Darryl Penso che le JOINs siano più facili da leggere perché la condizione per unire le tabelle è definita immediatamente lì invece che "da qualche parte" nella WHEREclausola. Preferisco riservare la WHEREclausola per limitare il set di dati (ad es. WHERE DATE > (SYSDATE - 1)) Anziché definire anche il modo in cui le tabelle si relazionano tra loro (ad es WHERE T1.ID = T2.ID.). Per una piccola tabella come nell'esempio in questione fa poca differenza, ma per le query di grandi dimensioni che coinvolgono più tabelle e diverse condizioni, penso che la query sia molto più semplice da capire.
ImaginaryHuman072889

61

Dovrebbero essere esattamente gli stessi. Tuttavia, come pratica di codifica, preferirei vedere Join. Esprime chiaramente le tue intenzioni,


8
Sono d'accordo. Soprattutto se ti unisci a più tabelle, è molto più semplice analizzare un'istruzione select se stai eseguendo un join esplicito.
Paul Morie,

13
Infatti. I join rappresentano una relazione semantica tra due set di dati, ma un punto suggerisce un set filtrato. +1
EightyOne Unite,

26

utilizzando JOIN semplifica la lettura del codice, poiché si spiega da sé.

Non c'è differenza di velocità (l' ho appena testato ) e il piano di esecuzione è lo stesso.


Grazie. stavo cercando una compressione rapida tra questi due metodi.
Farhad Navayazdan,

14

Non so di Oracle, ma so che la vecchia sintassi viene deprecata in SQL Server e alla fine scomparirà. Prima di utilizzare quella vecchia sintassi in una nuova query, avrei verificato cosa Oracle intendesse farne.

Preferisco la sintassi più recente piuttosto che la miscelazione dei criteri di join con altre condizioni necessarie dove. Nella sintassi più recente è molto più chiaro ciò che crea il join e quali altre condizioni vengono applicate. Non è un grosso problema in una query breve come questa, ma diventa molto più confuso quando si dispone di una query più complessa. Poiché le persone apprendono dalle query di base, tenderei a preferire che le persone imparino a utilizzare la sintassi del join prima che ne abbiano bisogno in una query complessa.

E ancora non conosco Oracle in modo specifico, ma so che la versione di SQL Server del join sinistro di vecchio stile è imperfetta anche in SQL Server 2000 e fornisce risultati incoerenti (a volte un join sinistro a volte un cross join), quindi non dovrebbe mai essere Usato. Speriamo che Oracle non abbia lo stesso problema, ma certamente i join destro e sinistro possono essere più difficili da esprimere correttamente nella vecchia sintassi.

Inoltre è stata la mia esperienza (e ovviamente questa è un'opinione strettamente personale, potresti avere un'esperienza diversa) che gli sviluppatori che usano i join standard ANSII tendono ad avere una migliore comprensione di ciò che è un join e cosa significa in termini di ottenere dati fuori dal database. Credo che sia perché la maggior parte delle persone con una buona conoscenza del database tendono a scrivere query più complesse e quelle che mi sembrano molto più facili da mantenere utilizzando lo standard ANSII rispetto al vecchio stile.


1
Fratello Amen. Abbasso i JOINERS !!
ScottCher,

14

[Per un punto bonus ...]

L'uso della sintassi JOIN consente di commentare più facilmente il join in quanto è tutto incluso su una riga. Questo può essere utile se si esegue il debug di una query complessa

Come tutti gli altri dicono, sono funzionalmente uguali, tuttavia il JOIN è più chiaro di una dichiarazione di intenti. Pertanto, in alcuni casi può essere utile l'ottimizzatore delle query nelle attuali versioni di Oracle (non ho idea se lo fa), può aiutare l'ottimizzatore di query nelle versioni future di Oracle (nessuno ha idea) o può aiutare se si cambia il fornitore del database.


2
Oppure ... modifica facilmente i JOIN INNER in JOIN SINISTRA, così vedrai quale join ti farà perdere le righe previste. Lo faccio perché eseguo l'intera query in una sola volta. Se commentate INNER JOINS, dovete fare un processo di eliminazione. Ci vuole più tempo Ma +1 per te perché questo è uno dei miei motivi preferiti di INNER JOIN oltre alla leggibilità!
Matthew McPeak,

13

Sono logicamente identici, ma nelle versioni precedenti di Oracle che adottavano la sintassi ANSI c'erano spesso bug con esso in casi più complessi, quindi a volte incontrerai resistenza dagli sviluppatori Oracle quando lo utilizzi.


Le versioni precedenti di Oracle avevano bug con questo? Quanto presto? Quali versioni?
ScottCher,

Metalink ha dettagli ... si aprono dappertutto.
David Aldridge,

7

Le prestazioni dovrebbero essere identiche, ma suggerirei di utilizzare la versione join a causa di una maggiore chiarezza quando si tratta di join esterni.

Anche i prodotti cartesiani non intenzionali possono essere evitati utilizzando la versione join.

Un terzo effetto è una lettura SQL più semplice con una condizione WHERE più semplice.


Penso davvero che la chiave siano gli effetti involontari in cui i criteri sono ambigui. Se specifichi il tipo di join, sai esattamente cosa stai ricevendo. Ho scoperto che database diversi e persino versioni diverse della stessa piattaforma di database gestiranno valori null in modo diverso in un join implicito. Quando specifichi interno / esterno sinistro / destro, passi il tempo a pensare a quale sia corretto. Quando usi il metodo ambiguo, supponi che funzioni come speri / intendi.
Steve Kallestad,

6

Non dimenticare che in Oracle, a condizione che gli attributi della chiave di join abbiano lo stesso nome in entrambe le tabelle, puoi anche scrivere questo come:

select *
from Table1 inner join Table2 using (ID);

Anche questo ha lo stesso piano di query, ovviamente.


Ho ritirato l'edizione perché la revisione precedente ha cambiato il significato della risposta
juan,

5

In uno scenario in cui le tabelle sono in terza forma normale, i join tra le tabelle non devono cambiare. Vale a dire aderire a CLIENTI e PAGAMENTI dovrebbero rimanere sempre gli stessi.

Tuttavia, dovremmo distinguere i join dai filtri . I join riguardano le relazioni e i filtri riguardano il partizionamento complessivo.

Alcuni autori, riferendosi allo standard (cioè Jim Melton; Alan R. Simon (1993). Comprensione del nuovo SQL: una guida completa. Morgan Kaufmann. Pp. 11-12. ISBN 978-1-55860-245-8.) , ha scritto dei vantaggi dell'adozione della sintassi JOIN su tabelle separate da virgole nella clausola FROM.

Sono totalmente d'accordo con questo punto di vista.

Esistono diversi modi per scrivere SQL e ottenere gli stessi risultati, ma per molti di coloro che fanno il lavoro di squadra, la leggibilità del codice sorgente è un aspetto importante e certamente separare il modo in cui le tabelle si relazionano tra loro da filtri specifici è stato un grande balzo nel senso di chiarire l'origine codice.


Inner join on significa cross join dove. La virgola è cross join con precedenza inferiore rispetto ai join di parole chiave. Su vs "filtro" è irrilevante per il join interno. Gli NF sono irrilevanti per l'interrogazione. Nulla nella norma promuove i join di parole chiave rispetto alla virgola. Le ottimizzazioni di base trattano e sono simili. Questa risposta è un mucchio di idee sbagliate.
philipxy

1) Suppongo che @philipxy stia cercando di dire "Nelle tabelle della clausola FROM separate da virgola hanno lo stesso significato delle tabelle CROSS JOINed." Sono d'accordo. Ovviamente, è possibile attenersi alla sintassi precedente e che può coesistere con le clausole JOIN. Gli ottimizzatori RDBMS comprenderanno perfettamente entrambi i casi come uguali (nel caso siano ovviamente equivalenti) ed elaboreranno lo stesso piano.
abrittaf

4

In PostgreSQL, non c'è assolutamente alcuna differenza: entrambi equivalgono allo stesso piano di query. Sono sicuro al 99% che è anche il caso di Oracle.


2

Sono entrambi join interni che fanno la stessa cosa, uno usa semplicemente la sintassi ANSI più recente.


2

Funzionalmente sono gli stessi che è stato detto. Sono d'accordo però che fare il join è meglio per descrivere esattamente cosa vuoi fare. Molte volte ho pensato di sapere come avrei voluto interrogare qualcosa fino a quando ho iniziato a fare i join e mi sono reso conto che volevo fare una query diversa da quella originale nella mia testa.


1

È vero che, funzionalmente, entrambe le query devono essere elaborate allo stesso modo. Tuttavia, l'esperienza ha dimostrato che se si seleziona da viste che utilizzano la nuova sintassi del join, è importante strutturare anche le query utilizzandolo. L'ottimizzatore di Oracle può essere confuso se una vista utilizza un'istruzione "join", ma una query che accede alla vista utilizza il metodo tradizionale di unione nella clausola "where".


Questo è più un problema con le viste che con i join.
inesistente il

0

Sebbene l'identità di due query sembri ovvia a volte accadono alcune cose strane. Sono arrivato alla domanda che ha piani di esecuzione diversi quando si sposta il predicato di join da JOIN a WHERE in Oracle 10g (per il piano WHERE è meglio), ma non riesco a riprodurre questo problema in tabelle e dati semplificati. Penso che dipenda dai miei dati e dalle mie statistiche. L'ottimizzatore è un modulo abbastanza complesso e talvolta si comporta magicamente.

Ecco perché non possiamo rispondere a questa domanda in generale perché dipende dai DB interni. Ma dovremmo sapere che la risposta non deve essere " nessuna differenza ".


0

ho avuto questo enigma oggi quando ho ispezionato uno dei timeout della nostra sp in produzione, ho cambiato un join interno su una tabella costruita da un feed XML in una clausola 'dove' invece .... il tempo medio di esecuzione ora è di 80 ms su 1000 esecuzioni, mentre prima che il valore medio di exec fosse di 2,2 secondi ... la principale differenza nel piano di esecuzione è la scomparsa di una ricerca chiave ... Il messaggio che non conoscerai fino a quando non avrai provato usando entrambi i metodi.

Saluti.



0

Come ha detto Kiewik, il piano di esecuzione è lo stesso.

La dichiarazione JOIN è solo più facile da leggere, rendendo più facile non dimenticare la condizione ON e ottenere un prodotto cartesiano. Questi errori possono essere piuttosto difficili da rilevare nelle query lunghe utilizzando più join di tipo: SELEZIONA * DA t1, t2 DOVE t1.id = t2.some_field.

Se si dimentica solo una condizione di join, si ottiene molto tempo per eseguire una query che restituisce troppi record ... davvero troppi. Alcuni utenti usano un DISTINCT per correggere la query, ma è ancora molto lungo da eseguire.

Questo è esattamente il motivo per cui l'uso dell'istruzione JOIN è sicuramente la migliore pratica: una migliore manutenibilità e una migliore leggibilità.

Inoltre, se ricordo bene, JOIN è ottimizzato per quanto riguarda l'utilizzo della memoria.


0

Ho un'aggiunta a quella buona risposta :

Questo è ciò che viene definito rispettivamente come SQL92 e SQL89, non c'è alcuna differenza di prestazioni tra loro anche se puoi omettere la parola INNER (usare solo JOIN è abbastanza chiaro e nella query più semplice salvi 5 tratti di tastiera ora immagina quanti tratti ci sono in grande quelli).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.