2009-09-09 16 views
21

Ho una query relativamente semplice che unisce due tabelle. I criteri "Dove" possono essere espressi nei criteri di join o come clausola where. Mi chiedo quale sia più efficiente.Criteri di filtro SQL nei criteri di join o clausola where che è più efficiente

Query è trovare le vendite massime per un venditore dall'inizio fino a quando non sono stati promossi.

Caso 1

select salesman.salesmanid, max(sales.quantity) 
from salesman 
inner join sales on salesman.salesmanid =sales.salesmanid 
        and sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

Caso 2

select salesman.salesmanid, max(sales.quantity) 
from salesman 
inner join sales on salesman.salesmanid =sales.salesmanid 
where sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

Nota Caso 1 manca una clausola in cui tutto

RDBMS è SQL Server 2005

EDIT Se la seconda pezzo di il criterio di join o la clausola where era sales.salesdate < alcune date fisse quindi non è in realtà alcun criterio di unione delle due tabelle che modifica la risposta.

+0

Cosa c'è di sbagliato nel testare effettivamente il tempo impiegato da queste query? – ChristopheD

+2

Poiché la query viene memorizzata nella cache ma grazie, davvero – Gratzy

+1

@Gratzy - DBCC FREEPROCCACHE http://msdn.microsoft.com/en-us/library/ms174283.aspx –

risposta

20

Non vorrei usare la performance come fattore decisivo qui - e onestamente, non penso che ci sia alcuna differenza di prestazioni misurabili tra questi due casi, davvero.

Userei sempre il caso n. 2: perché? Perché secondo me, dovresti solo inserire i criteri effettivi che stabiliscono il JOIN tra le due tabelle nella clausola JOIN - tutto il resto appartiene alla clausola WHERE.

Solo una questione di mantenere le cose pulite e mettere le cose a cui appartengono, IMO.

Ovviamente, ci sono casi con LEFT OUTER JOINs in cui il posizionamento dei criteri fa la differenza in termini di risultati che vengono restituiti - questi casi sarebbero esclusi dalla mia raccomandazione, ovviamente.

Marc

+1

+1 - buona risposta marc –

+0

IMO si potrebbe sostenere che il caso n. 1 è migliore per l'incapsulamento (in questo caso, la clausola WHERE viene utilizzata solo per i criteri della tabella principale). –

0

Può sembrare irriverente, ma la risposta è qualsiasi query per la quale l'analizzatore di query produce il piano più efficiente.

A mio parere, sembrano equivalenti, quindi l'analizzatore di query potrebbe produrre piani identici, ma è necessario testarlo.

0

Né è più efficiente, utilizzando il metodo in cui è considerato il vecchio modo di farlo (http://msdn.microsoft.com/en-us/library/ms190014.aspx). Puoi guardare il piano di esecuzione e vedere che fanno la stessa cosa.

+0

Il mio esempio non era la migliore modifica la seconda parte della clausola join e o where per essere una data fissa invece di una data nella tabella del venditore. – Gratzy

+0

Ahh okay, beh, in entrambi i casi il piano di esecuzione è tuo amico. Analizzalo per trovare quale ha le migliori prestazioni. La mia scommessa è che saranno identici. –

1

Non credo che troverete una risposta finita per questo che si applica a tutti i casi. I 2 non sono sempre intercambiabili - dal momento che per alcune query (alcuni join di sinistra) si ottengono risultati diversi posizionando i criteri nella riga WHERE vs FROM.

Nel tuo caso, dovresti valutare entrambe queste query. In SSMS, è possibile visualizzare i piani di esecuzione stimati e effettivi di entrambe queste query: sarebbe un buon primo passo per determinare quale sia più ottimale. È anche possibile visualizzare l'ora & IO per ciascuna (imposta le statistiche su, impostare le statistiche su on) - e che fornirà anche le informazioni per prendere una decisione.

Nel caso delle domande nella tua domanda - Scommetto che entrambi verranno con lo stesso piano di query - quindi in questo caso potrebbe non avere importanza, ma in altri potrebbe potenzialmente produrre piani diversi.

Provate a vedere la differenza tra il 2 ...

SET STATISTICS IO ON 
SET STATISTICS TIME ON 

select salesman.salesmanid, 
     max(sales.quantity) 
from salesmaninner join sales on salesman.salesmanid =sales.salesmanid 
     and sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

select salesman.salesmanid, 
     max(sales.quantity) 
from salesmaninner join sales on salesman.salesmanid = sales.salesmanid 
where sales.salesdate < salesman.promotiondate 
group by salesman.salesmanid 

SET STATISTICS TIME OFF 
SET STATISTICS IO OFF 
+0

Questo sarebbe specificamente inner join – Gratzy

+1

Gratzy - in quel caso, sono d'accordo con marc_s - i criteri di filtro dovrebbero essere tenuti nella porzione in cui della query, ed i criteri di join dovrebbero essere tenuti in FROM parte della query. –

+0

È importante però che la tabella dei criteri where abbia molte, molte più righe. So che potrebbe sembrare banale, ma mi stavo chiedendo se sarebbe stato quindi meglio farne parte dei criteri di join invece della clausola where – Gratzy

0

acquisire familiarità con il piano di esecuzione stimato in SQL Management Studio !! Come altri hanno già detto, sei alla mercé dell'analizzatore, non importa quello che fai, fidati delle sue stime. Direi che i due che hai fornito avrebbero prodotto lo stesso identico piano.

Se si tratta di un tentativo di cambiare una cultura dello sviluppo, scegliere quello che ti dà un piano migliore; per quelli che sono identici, segui la cultura

Ho commentato questo su altri post di "efficienza" come questo (è sia sincero che sarcastico) - se questo è dove risiedono i colli di bottiglia, allora il cinque in alto tu e il tuo team.

+1

Sì, ho familiarità con il piano di esecuzione stimato. Tuttavia, non mi dirà perché genera il piano di esecuzione come fa. Stavo cercando di capire perché uno potrebbe essere più efficiente dell'altro. – Gratzy

+0

@Gratzy: http://www.amazon.com/Gurus-Guide-Server-Architecture-Internals/dp/0201700476 –

3

preferisco avere alcun criterio hard coded nel join. Rende l'SQL molto più leggibile e portatile.

Leggibilità: È possibile visualizzare esattamente quali dati si otterranno perché tutti i criteri di tabella sono scritti proprio lì nel join. In grandi dichiarazioni, i criteri possono essere sepolti all'interno di altre 50 espressioni ed è facilmente trascurato.

Portabilità: È sufficiente copiare un blocco dalla clausola FROM e incollarlo da qualche altra parte. Ciò fornisce i join e tutti i criteri che è necessario seguire. Se si utilizzano sempre questi criteri quando si uniscono queste due tabelle, inserirle nel join è la più logica.

Per esempio:

FROM 
table1 t1 
JOIN table2 t2_ABC ON 
    t1.c1 = t2_ABC.c1 AND 
    t2_ABC.c2 = 'ABC' 

Se avete bisogno di ottenere una seconda colonna di tabella 2 Basta copiare quel blocco in Blocco note, ricerca/repalce "ABC" e presto e tutto il nuovo blocco di codice pronto a incollare nuovamente.

In aggiunta: È anche più semplice cambiare tra un join interno ed uno esterno senza doversi preoccupare di alcun criterio che potrebbe essere presente nella clausola WHERE.

mi riservo clausola WHERE rigorosamente per i criteri di runtime ove possibile.

Per quanto riguarda l'efficienza: Se ci si riferisce alla velocità di esecuzione, allora come tutti gli altri hanno dichiarato, è ridondante. Se mi riferisci a un debugging e riutilizzo più semplice, allora preferisco l'opzione 1.

+0

In sintesi, i criteri nel join è meglio per l'incapsulamento, e una maggiore incapsulamento di solito è meglio. –

1

Una cosa che voglio dire finalmente come ho notificato, prima che .. Entrambi i modi possono dare la stessa performance o usare i criteri a Dove la clausola può essere leggermente più veloce come si può trovare in alcune risposte ..

Ma ho identificato una differenza, è possibile utilizzare per le vostre esigenze logiche ..

  1. Utilizzando i criteri alla ON clausola non filtrerà/saltare le righe per selezionare invece il join colonne sarebbero nulli sulla base delle condizioni

  2. Usando i criteri in Dove clausola può filtrare/ignorare le righe all'intera risultati

0

Il caso 1 (i criteri nel JOIN) è migliore per l'incapsulamento e un maggiore incapsulamento è di solito una buona cosa: riduzione delle omissioni di copia/incolla in un'altra query, diminuzione dei bug se successivamente convertiti in SINISTRA COMUNE e aumento della leggibilità (materiale correlato insieme e meno "rumore" nella clausola WHERE). In questo caso, la clausola WHERE acquisisce solo i criteri della tabella principale oi criteri che si estendono su più tabelle.

Problemi correlati