2009-04-30 8 views
7

Dato queste due domande:è meglio mettere più logica nella tua clausola ON o dovrebbe avere solo il minimo necessario?

Select t1.id, t2.companyName 
from table1 t1 
    INNER JOIN table2 t2 on t2.id = t1.fkId 
WHERE t2.aField <> 'C' 

O:

Select t1.id, t2.companyName 
from table1 t1 
    INNER JOIN table2 t2 on t2.id = t1.fkId and t2.aField <> 'C' 

c'è una differenza dimostrabile tra i due? Mi sembra che la clausola "t2.aField <> 'C'" verrà eseguita su ogni riga in t2 che soddisfi i criteri di join. Sono errato?

Aggiornamento: Ho eseguito un "Include Actual Execution Plan" in SQL Server. Le due domande erano identiche.

risposta

4

Preferisco utilizzare i criteri di join per spiegare come i tavoli sono uniti. Quindi posizionerei la clausola aggiuntiva nella sezione where.

spero (anche se non ho statistiche), che SQL Server sarebbe abbastanza intelligente per trovare il piano di query ottimale indipendentemente dalla sintassi da utilizzare.

Tuttavia, se si dispone di indici che hanno anche id, e lontano, nelle loro, vorrei suggerire posizionarli uno accanto all'altro nella inner join criteri.

Sarebbe interessante vedere il piano di query in questi 2 (o 3) scenari e vedere cosa succede. Bella domanda

+0

Sono d'accordo, se fa parte di un indice dovrebbe essere nella clausola ON e se si tratta di criteri di filtro dovrebbe andare nella clausola WHERE. Questo ha abbastanza upvotes per chiamarlo la risposta. – jcollum

3

C'è una differenza. Dovresti fare un PIANO DI SPIEGAZIONE per entrambi i selettivi e vederlo in dettaglio.

Come per una spiegazione più semplice: Il WHERE viene eseguito solo dopo l'unione delle due tabelle, quindi viene eseguito per ogni riga restituita dalla aderire e non nececerally ciascuno dal table2.

prestazioni saggio del suo meglio per eliminare risultati indesiderati nella fase iniziale quindi non ci dovrebbero essere meno righe per raggiunge, in cui le clausole o altre operazioni per affrontare in seguito.

Nel secondo esempio, ci sono 2 colonne che devono essere lo stesso per le righe da unire insieme in modo che di solito darà risultati diversi rispetto al primo.

+0

Un prodotto di database così stupido come quello che sarebbe un braindead. Naturalmente qualsiasi implementazione del database che valga il suo nome non crea join inutili –

+0

Sì, l'ho già provato in MySQL. Almeno nel mio caso, non c'era differenza di velocità –

+0

Per un semplice join naturale di due tabelle non ci sarà alcuna differenza. Ma diventa evidente quando devi unirti a 5-6 tavoli e quindi anche l'implementazione del database "intelligente" dovrà essere aiutata. – Azder

0

Preferisco la prima richiesta. Il server SQL utilizzerà il miglior tipo di join per la query in base agli indici in uso, dopodiché verrà applicata la clausola WHERE. Ma puoi eseguire entrambe le query contemporaneamente, esaminare i piani di esecuzione, confrontare e scegliere il più veloce (ottimizza anche l'aggiunta di indici).

+0

tieni d'occhio le prestazioni delle tue scritture ogni volta che aggiungi degli indici. Esistono metodi disponibili per i tuoi indici che li rendono "facili da scrivere". – yetanotherdave

2

Dipende.

SELECT 
    t1.foo, 
    t2.bar 
FROM 
    table1 t1 
    LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId 
WHERE 
    t2.SomeValue IS NULL 

è diverso da

SELECT 
    t1.foo, 
    t2.bar 
FROM 
    table1 t1 
    LEFT JOIN table2 t2 ON t1.SomeId = t2.SomeId AND t2.SomeValue IS NULL 

È diverso perché gli ex croci fuori tutti i record da T2 che hanno NULL nel t2.SomeValue e quelli di t1 che non sono fatto riferimento in T2. Quest'ultimo supera solo i record t2 che hanno NULL in t2.SomeValue.

Basta usare la clausola ON per la condizione di join e la clausola WHERE per il filtro.

+0

Ho usato un join interno nel mio esempio però. – jcollum

+0

l'esempio è diverso perché t2.SomeValue potrebbe essere nullo perché non è stato aggiunto o è stato aggiunto e il campo è nullo – jcollum

+0

La differenza è nel NULL. Nel join sinistro, t2.SomeValue sarà NULL quando * è effettivamente * NULL, * e * sarà NULL se un record da t1 non è referenziato. I set di risultati non sono uguali. L'unico modo per differenziare i due è usare la clausola ON. – Tomalak

0

a meno che non si stia lavorando su un'app per utente singolo o qualcosa di simile che crea un carico insignificante, le uniche considerazioni che significano qualcosa sono le modalità con cui il server elaborerà la query.

Le risposte che citano i piani di query danno buoni consigli.

Inoltre, imposta le statistiche io per avere un'idea di quante letture la query genererà (in particolare amo il post di Azder).

Pensa a ogni server DB come a una pompa di dati da disco a client. Quella pompa va più veloce se esegue solo l'IO necessario per portare a termine il lavoro. Se i dati sono nella cache, sarà ancora più veloce. Ma non vuoi leggere più di quanto hai bisogno dal disco - ciò comporterà lo spiazzamento dei dati utili della tua cache senza una buona ragione.

1

A meno che lo spostamento della condizione di join nella clausola where non modifichi il significato della query (come nell'esempio di join di sinistra sopra), non importa dove li si inserisce. SQL li riorganizzerà e, purché sia ​​provatamente equivalente, otterrai la stessa query.

Detto questo, penso che sia più una cosa logica/leggibile. Di solito metto tutto ciò che riguarda due tabelle nel join e tutto ciò che filtra nel dove.

+0

C'è un piccolo avvertimento a questa risposta. In teoria, non fa assolutamente alcuna differenza dove metti le tue condizioni. Tuttavia, in pratica, all'ottimizzatore viene concesso un periodo di tempo limitato per riorganizzare la query, pertanto potrebbe non aver avuto il tempo di riordinare le condizioni di partecipazione. Pertanto, in alcuni casi con query molto complicate, potrebbe essere importante. –

Problemi correlati