Differenza monumentale nel tempo di esecuzione tra le query quando si utilizza il suggerimento per la query RECOMPILE


16

Ho due query quasi identiche in esecuzione sulla stessa istanza di SQL Server 2005:

  1. La prima è la SELECTquery originale generata da LINQ (lo so, lo so ... non sono lo sviluppatore dell'applicazione, ma solo il DBA :).
  2. Il secondo è esattamente lo stesso del primo, aggiunto OPTION (RECOMPILE)a alla fine.

Nient'altro è stato cambiato.

Il primo impiega 55 secondi ogni volta che si avvia.
Il secondo richiede 2 secondi.

Entrambi i set di risultati sono identici.

Perché questo suggerimento genererebbe un guadagno così drammatico nelle prestazioni?

La voce Libri online su RECOMPILEnon offre una spiegazione molto dettagliata:

Indica a Motore di database di SQL Server di eliminare il piano generato per la query dopo l'esecuzione, forzando Query Optimizer a ricompilare un piano di query alla successiva esecuzione della stessa query. Senza specificare RECOMPILE, Motore di database memorizza nella cache i piani di query e li riutilizza. Durante la compilazione di piani di query, l'hint di query RECOMPILE utilizza i valori correnti di qualsiasi variabile locale nella query e, se la query si trova all'interno di una procedura memorizzata, i valori correnti passano a tutti i parametri.

RECOMPILE è un'utile alternativa alla creazione di una procedura memorizzata che utilizza la clausola WITH RECOMPILE quando è necessario ricompilare solo un sottoinsieme di query all'interno della procedura memorizzata, anziché l'intera procedura memorizzata. Per ulteriori informazioni, consultare Ricompilazione di stored procedure. RICOMPILE è utile anche quando si creano guide di piano. Per ulteriori informazioni, vedere Ottimizzazione delle query nelle applicazioni distribuite utilizzando le guide di piano.

Poiché la mia query ha molte variabili locali, la mia ipotesi è che SQL Server sia in grado di ottimizzarla (seriamente) quando utilizzo il OPTION (RECOMPILE)suggerimento per la query.

Ovunque guardi la gente dice che OPTION (RECOMPILE)dovrebbe essere evitato. La spiegazione di ciò è generalmente che l'utilizzo di questo suggerimento SQL Server non è in grado di riutilizzare questo piano di exection e quindi deve perdere tempo a ricompilarlo ogni volta.
(Ma) Dato il gigantesco vantaggio in termini di prestazioni, sono propenso a pensare che usare questo suggerimento per la query questa volta sarebbe una buona cosa.

Dovrei usarlo? In caso contrario, esiste un modo per forzare SQL Server a utilizzare un piano di esecuzione migliore senza questo suggerimento e senza alterare l'applicazione?

Risposte:


16

Come documentato nell'articolo Statistiche utilizzate dallo Strumento per ottimizzare le query in Microsoft SQL Server 2005

Se si utilizza una variabile locale in un predicato della query anziché un parametro o letterale, l'ottimizzatore ricorre a una stima di qualità ridotta o a un'ipotesi di selettività del predicato. Utilizzare parametri o valori letterali nella query anziché variabili locali

Quando l'ottimizzatore non ha alcuna statistica utilizzabile per una colonna, indovinerà che un =predicato corrisponderà al 10% delle righe, al BETWEEN9% e una qualsiasi delle >, >=, < and <=corrisponderà al 30%. Se sono disponibili statistiche di colonna, un =predicato verrà trattato in modo diverso come di seguito.

Anche quando in una query vengono utilizzate variabili locali, nel caso dei predicati di uguaglianza viene utilizzata una stima migliore di un'ipotesi. La selettività per le condizioni del modulo " @local_variable = column_name" viene stimata utilizzando la frequenza del valore medio dall'istogramma per nome_colonna. Pertanto, ad esempio, se la colonna nome_colonna contiene tutti i valori univoci, 1/(number of unique values in column)verrà utilizzata una stima della selettività di , che è accurata.

Quindi questo è essenzialmente lo stesso che usare per OPTIMIZE FOR (UNKNOWN). Potrebbe essere più preciso di 10%un'ipotesi semplice, ma non è su misura per i valori specifici che stai interrogando.

Per forzare SQL Server a ottimizzare una query ogni volta che viene eseguita e utilizzare i valori delle variabili locali per stimare cardinalità e costi durante l'ottimizzazione della query, aggiungere il RECOMPILEsuggerimento alla query.

Con l'uso di RECOMPILEte presumibilmente stai ottenendo stime di cardinalità più accurate e quindi un piano diverso con ordini di join / tipi di join più adatti al numero di righe restituite da diverse parti della query effettiva.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.