2010-01-14 14 views
93

Sono curioso quale dei seguenti aspetti sarebbe più efficiente?
Sono sempre stato un po 'cauto nell'usare IN perché credo che SQL Server trasformi il set di risultati in una grande affermazione IF. Per un grande risultato, questo potrebbe comportare prestazioni scadenti. Per i piccoli set di risultati, non sono sicuro che sia preferibile. Per i set di risultati di grandi dimensioni, EXISTS non sarebbe più efficiente?SQL Server IN vs. ESISTE Prestazioni

WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2) 

vs.

WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2]) 
+6

Il modo migliore per scoprirlo è provarlo e fare alcune misurazioni. –

+10

c'è ** got ** per essere un duplicato di gazillion per questo ...... –

+0

@marc_s: sì, ma penso che dipenda davvero dal caso. Immagino che la risposta canonica sia quella di klausbyskov (o chiunque possa rivendicare la precedente arte). – RedFilter

risposta

117

EXISTS sarà più veloce perché una volta che il motore ha trovato un colpo, si annullerà cercando, come la condizione si è dimostrato vero.
Con IN raccoglierà tutti i risultati dalla sottoquery prima di ulteriori elaborazioni.

+3

Questo è un buon punto. L'istruzione IN richiede a SQL Server di generare un set di risultati completo e quindi di creare una grande istruzione IF, credo. –

+63

Questo era vero ma nelle versioni correnti (almeno per il 2008) l'ottimizzatore è molto più intelligente ... in realtà tratta IN() proprio come un EXISTS(). –

+10

@'Aaron: sì, in genere l'optimzer produrrà internamente un piano migliore. Tuttavia, fare affidamento su scorciatoie interne potrebbe essere dannoso in scenari più complessi. –

-1

Fuori della parte superiore della mia testa e non garantisce che sia esatto: credo che il secondo sarà più veloce in questo caso.

  1. Nella prima, la sottoquery correlata causerà probabilmente l'esecuzione della sottoquery per ogni riga.
  2. Nel secondo esempio, la sottoquery deve essere eseguita una sola volta, poiché non correlata.
  3. Nel secondo esempio, IN si interrompe non appena trova una corrispondenza.
3

In questi casi, i piani di esecuzione saranno in genere identici, ma finché non vedrai come i fattori di ottimizzazione in tutti gli altri aspetti degli indici, ecc., Non lo saprai mai.

33

Ho eseguito alcuni test su SQL Server 2005 e 2008 e su EXISTS e IN sono tornati con lo stesso piano di esecuzione effettivo, come altri hanno affermato. L'ottimizzatore è ottimale. :)

Qualcosa di essere a conoscenza, però, ESISTE, IN, e si uniscono a volte può restituire risultati diversi se non la query frase giusto: http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210.aspx

1

Per ottimizzare il EXISTS, essere molto letterale; qualcosa deve solo essere lì, ma in realtà non è necessario alcun dato restituito dalla sub-query correlata. Stai solo valutando una condizione booleana.

Quindi:

WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

Poiché il correlato sub-query è RBAR, il primo colpo risultato rende la condizione vera, e viene elaborato oltre.

+0

Sarei sempre estremamente cauto nell'usare la codifica LEFT JOIN + NULL, perché è molto facile ottenere risultati mancati o distorti se non si presta molta attenzione alla gestione NULL. Raramente ho trovato una situazione in cui EXISTS o CTE (per trovare la duplicazione, o inserimento sintetico per dati mancanti), non soddisfano entrambi gli stessi requisiti e superano il LEFT JOIN + NULL –

+2

TOP 1 dovrebbe essere completo estraneo (o evento ridondante) se utilizzato con EXISTS. EXISTS ritorna sempre non appena trova una riga corrispondente. –

+0

Non ho visto alcun beneficio in termini di prestazioni con questo approccio finora. Si prega di mostrare alcuni screenshot dei piani di esecuzione – montewhizdoh

28

La risposta accettata è miope e la domanda un po 'allentato dal fatto che:

1) Né esplicitamente menzionato se un indice di rivestimento è presente in sinistra, destra, o entrambi i lati.

2) Né si tiene in considerazione la dimensione del set di input sul lato sinistro e di input sul lato destro.
(La domanda menziona solo un grande risultato impostato).

Credo che l'ottimizzatore è abbastanza intelligente per la conversione tra "in" vs "esiste" quando v'è una differenza di costo significativa a causa di (1) e (2), altrimenti si può solo essere usato come un suggerimento (es. esiste per incoraggiare l'uso di un indice ricercabile sul lato destro).

Entrambi i moduli possono essere convertiti per unire moduli internamente, avere l'ordine di join invertito ed eseguire come loop, hash o unione, in base ai conteggi di riga stimati (a sinistra ea destra) e all'indice di esistenza a sinistra, a destra o entrambe le parti.

+2

non so perché questa eccellente risposta non ha ottenuto più attenzione. Comprendere l'indice/struttura per entrambe le parti potrebbe avere un impatto su di me. Ben detto. – SheldonH

Problemi correlati