Domanda

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

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

Nel semplicistico codice di esempio sopra, sto specificando la strategia JOIN, mentre se tralascio l'hash " hash " la parola chiave SQL Server eseguirà un MERGE JOIN dietro le quinte (secondo il "piano di esecuzione effettivo").

È stato utile?

Soluzione

L'ottimizzatore 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.

Lascerei da solo a meno che tu non abbia una query molto complessa o enormi quantità di dati in cui semplicemente non è in grado di produrre un buon piano. Quindi lo prenderei in considerazione.

Ma nel tempo, quando i dati cambiano / crescono o gli indici cambiano ecc., il tuo suggerimento JOIN diventerà obsoleto e impedirà un piano ottimale. Un suggerimento JOIN può ottimizzare solo per quella singola query al momento dello sviluppo con quel set di dati che hai.

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

Normalmente ho risolto un cattivo join cambiando la mia query, aggiungendo / cambiando un indice o spezzandolo (es. prima caricare una tabella temporanea). Oppure la mia query era sbagliata, o avevo una conversione implicita del tipo di dati, o metteva in evidenza 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 eseguito il refactoring.

Modifica:

Oggi ho avuto una conversione in cui alcuni colleghi li useranno per forzare un piano di query errato (con NOLOCK e MAXDOP 1) per "incoraggiare". migrazione da viste nidificate complesse legacy che uno dei loro sistemi downstream chiama direttamente.

Altri suggerimenti

Quando provare un suggerimento hash, che ne dici di:

  • Dopo aver verificato l'esistenza di indici adeguati su almeno uno dei tabelle.
  • Dopo aver tentato di riorganizzare la query. Cose come la conversione si unisce a " in " o "esiste", cambiando l'ordine dei join (che in realtà è solo un suggerimento comunque), spostando la logica da cui la clausola si unisce alla condizione, ecc.

Alcune regole di base su quando un hash join è efficace sono 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 là fuori su come funziona un hash join.

Perché usare i suggerimenti di join (hash / merge / loop con effetto collaterale dell'ordine di forza)?

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

È probabile che un suggerimento fornito non sia ideale per alcune circostanze, ma fornisce tempi di esecuzione più coerenti prevedibili. Gli scenari peggiori previsti e gli scenari migliori dovrebbero essere pre-testati quando si utilizza un suggerimento. I runtime prevedibili sono fondamentali per i servizi Web in cui si preferisce una query nominale [.3s, .6s] rigidamente ottimizzata rispetto a una che può ad esempio variare di [.25, 10.0s]. Variazioni di runtime elevate possono verificarsi con statistiche aggiornate di recente e seguite le migliori pratiche.

Quando si esegue il test in un ambiente di sviluppo, è necessario disattivare " barare " anche per evitare variazioni di runtime 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 potrebbe essere uguale al suggerimento per l'opzione (ricompilazione).

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

I join hash si parallelizzano e si ridimensionano meglio di qualsiasi altro join e sono ottimi per massimizzare la produttività nei data warehouse.

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

Lo so, sovraccaricare le colonne è male. A volte, devi conviverci.

L'ottimizzatore del piano logico non ti assicura di trovare la soluzione ottimale: un algoritmo esatto è troppo lento per essere utilizzato in un server di produzione; invece vengono usati alcuni algoritmi avidi.

Quindi, la logica alla base di questi comandi è quella di consentire all'utente di specificare la strategia di join ottimale, nel caso in cui l'ottimizzatore non riesca a capire quale sia davvero il migliore da adottare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top