2009-04-28 8 views
11

Quali sono i vantaggi, se ve ne sono, di fare esplicitamente un HASH JOIN su un normale JOIN (in cui SQL Server deciderà la migliore strategia JOIN)? Ad esempio:vantaggi nello specificare HASH JOIN semplicemente facendo un JOIN?

select pd.* 
from profiledata pd 
inner hash join profiledatavalue val on val.profiledataid=pd.id 

Nel codice di esempio semplicistico sopra, sto specificando la strategia di join, mentre se lascio fuori il "hash" parola chiave di SQL Server farà un merge join dietro le quinte (per la "effettiva progetto esecutivo").

risposta

12

L'optmiser fa un lavoro abbastanza buono per l'uso quotidiano. Tuttavia, in teoria potrebbero essere necessarie 3 settimane per trovare il piano perfetto all'estremo, quindi c'è la possibilità che il piano generato non sia l'ideale.

Vorrei lasciarlo da solo a meno che non si disponga di una query molto complessa o di enormi quantità di dati in cui semplicemente non è possibile produrre un buon piano. Allora lo considererei.

Ma nel tempo, man mano che i dati cambiano/aumentano o cambiano gli indici, il tuo suggerimento JOIN diventa obsoleto e impedisce un piano ottimale. Un suggerimento JOIN può solo ottimizzare per quella singola query al momento dello sviluppo con quel set di dati che hai.

Personalmente, non ho mai specificato un suggerimento JOIN in alcun codice di produzione.

In genere ho risolto un errore di inserimento cambiando la query, aggiungendo/modificando un indice o scomporlo (ad esempio, prima carica una tabella temporanea). O la mia query era semplicemente sbagliata, o avevo una conversione implicita del tipo di dati, o evidenziava un difetto nel mio schema ecc.

Ho visto altri sviluppatori usarli ma solo dove avevano viste complesse nidificate su viste complesse e hanno causato problemi successivi quando hanno refactored.

Edit:

ho avuto una conversione oggi, dove alcuni colleghi stanno per usarli per forzare un piano di query cattivo (con NOLOCK e MAXDOP 1) di "incoraggiare" la migrazione da legacy complesso viste nidificate che uno dei il loro sistema a valle chiama direttamente.

0

Il programma di ottimizzazione logica non garantisce che trova la soluzione ottimale: un algoritmo esatto è troppo lento da utilizzare in un server di produzione; invece vengono utilizzati alcuni algoritmi grezzi.

Quindi, la logica alla base di questi comandi è quella di consentire all'utente di specificare la strategia di unione ottimale, nel caso l'ottimizzatore non riesca a risolvere ciò che è veramente il migliore da adottare.

2

I join di hash sono paralleli e scalabili meglio di qualsiasi altro join e sono ideali per massimizzare il throughput nei data warehouse.

1

L'unico suggerimento che abbia mai visto nel codice di spedizione era OPZIONE (ORDINE DI FORZA). Il bug stupido in SQL Query Optimizer generava un piano che tentava di unire un varchar non filtrato e un identificatore univoco. L'aggiunta di FORCE ORDER ha causato prima l'esecuzione del filtro.

Lo so, il sovraccarico delle colonne è negativo. A volte devi conviverci.

+0

Modifica Sto per aggiungere un OPTION (MAXDOP 1) per impedire a un addetto al background di masticare tutta la potenza del processore. – Joshua

3

Quando per cercare un suggerimento hash, che ne dici:

  • Dopo aver verificato che esistono indici adeguati su almeno uno dei tabelle.
  • Dopo aver provato a riorganizzare la query.Cose come la conversione si unisce a "in" o "esiste", cambiando ordine di join (che è davvero solo un suggerimento in ogni caso), spostando la logica da cui la clausola di condizione di join, ecc

Alcune regole di base su quando un hash join è efficace quando una condizione di join non esiste come indice di tabella e quando le dimensioni delle tabelle sono diverse. Se stai cercando una descrizione tecnica, ci sono alcune buone descrizioni sul funzionamento di un hash join.

Perché utilizzare un suggerimento di join (hash/merge/loop con effetto collaterale dell'ordine di forza)?

  • Per evitare l'esecuzione estremamente lenta (.5 -> 10.0s) di casi d'angolo.
  • Quando l'ottimizzatore sceglie costantemente un piano mediocre.

Un suggerimento fornito può non essere ideale per alcune circostanze, ma fornisce runtime più coerenti e prevedibili. Il caso peggiore atteso e gli scenari migliori dovrebbero essere pre-testati quando si utilizza un suggerimento. I runtime prevedibili sono fondamentali per i servizi Web in cui è preferibile una query nominale [.3s, .6s] rigidamente ottimizzata su una che può raggiungere [.25, 10.0s], ad esempio. Grandi variazioni di runtime possono verificarsi con statistiche appena aggiornate e le migliori pratiche seguite.

Quando si esegue il test in un ambiente di sviluppo, è necessario disattivare anche "cheating" per evitare variazioni del tempo di esecuzione caldo/freddo. Da un altro post ...

CHECKPOINT -- flushes dirty pages to disk 
DBCC DROPCLEANBUFFERS -- clears data cache 
DBCC FREEPROCCACHE -- clears execution plan cache 

L'ultima opzione può essere lo stesso come l'opzione (ricompilazione) suggerimento.

Anche il MAXDOP e il caricamento della macchina possono fare un'enorme differenza in runtime. La materializzazione di CTE in tabelle temporanee è anche un buon meccanismo di blocco e qualcosa da considerare.