2016-02-25 24 views
5

C'è qualche differenza, per quanto riguarda le prestazioni, quando ci sono molte query eseguite con (diversi) valori costanti all'interno di una clausola where, al contrario di avere una query con parametri dichiarati in cima, dove invece il valore del parametro sta cambiando?SQL: qualsiasi differenza di prestazioni utilizzando valori costanti rispetto ai parametri?

interrogazione campione con con valore costante nella clausola WHERE:

select 
* 
from [table] 
where [guid_field] = '00000000-0000-0000-000000000000' --value changes 

Proposto (migliore?) Query con parametri dichiarati:

declare @var uniqueidentifier = '00000000-0000-0000-000000000000' --value changes 

select 
* 
from [table] 
where [guid_field] = @var 

C'è qualche differenza? Sto osservando i piani di esecuzione di qualcosa di simile alle due query precedenti e non vedo alcuna differenza. Tuttavia, mi sembra di ricordare che se si utilizzano valori costanti nelle istruzioni SQL, il server SQL non riutilizzerà gli stessi piani di esecuzione delle query o qualcosa del genere che produce prestazioni peggiori, ma è vero?

+0

Le regole per la compilazione e stashing query per SQL Server sono piuttosto complesse. In generale, penso che compili la query basata sui primi parametri passati. Quindi, se il piano di query è memorizzato nella cache e si modificano i parametri, l'utilizzo successivo del piano potrebbe non essere ottimale per i nuovi valori. Tuttavia, dovrebbe andare bene per la prima chiamata, che genera il piano di query. Nota: iniziare con una tabella vuota e quindi compilare la tabella può anche influire sul piano migliore, anche con lo stesso valore passato. –

risposta

1

Qui è importante distinguere tra parametri e variabili. I parametri sono passati a procedure e funzioni, le variabili sono dichiarate.

Indirizzando le variabili, che è ciò che l'SQL nella domanda ha, durante la compilazione di un batch ad-hoc, SQL Server compila ogni istruzione all'interno di esso. Quindi, quando si compila la query con una variabile, non torna indietro per controllare alcun compito, quindi compilerà un piano di esecuzione ottimizzato per una variabile sconosciuta. Alla prima esecuzione, questo piano di esecuzione verrà aggiunto alla cache del piano, quindi le esecuzioni future potranno e riutilizzeranno questa cache per tutti i valori delle variabili.

Quando si passa una costante, la query viene compilata in base a tale valore specifico, quindi è possibile creare un piano più ottimale, ma con il costo aggiuntivo della ricompilazione.

Quindi, per rispondere alla tua domanda in particolare:

Tuttavia, mi sembra di ricordare che se si utilizza valori costanti nelle istruzioni SQL server SQL non riutilizzare gli stessi piani di esecuzione di query, o qualcosa in tal senso ciò causa prestazioni peggiori, ma è vero?

Sì, è vero che lo stesso piano non può essere riutilizzato per valori costanti diversi, ma ciò non causa necessariamente prestazioni peggiori. È possibile che un piano più appropriato possa essere utilizzato per quella particolare costante (ad esempio, scegliendo la ricerca di un segnalibro rispetto alla scansione dell'indice per i dati sparsi) e questa modifica del piano di query potrebbe superare il costo della ricompilazione. Così come è quasi sempre il caso per quanto riguarda le domande di prestazioni SQL. La risposta è dipende da.

Per i parametri, il comportamento predefinito è che il piano di esecuzione viene compilato in base a quando i parametri utilizzati quando la procedura o la funzione viene eseguita per la prima volta.

ho risposto a domande simili prima in modo molto più dettagliato con esempi, che coprono un sacco di quanto sopra, in modo piuttosto che ripetere i vari aspetti di essa mi limiterò a collegare le domande:

0

Innanzitutto, si noti che una variabile locale non è la stessa come parametro.

Supponendo che la colonna sia indicizzata o che disponga di statistiche, SQL Server utilizza l'istogramma delle statistiche per calcolare una stima del conteggio delle righe in base al valore costante fornito. La query verrà anche parametrizzata automaticamente e memorizzata nella cache se è banale (produce lo stesso piano indipendentemente dai valori) in modo che le esecuzioni successive evitino i costi di compilazione delle query.

Una query con parametri genera anche un piano utilizzando l'istogramma delle statistiche con il valore del parametro inizialmente fornito. Il piano viene memorizzato nella cache e riutilizzato per le esecuzioni successive, indipendentemente dal fatto che sia o meno banale.

Con una variabile locale, SQL Server utilizza la cardinalità statistica generale per generare il piano perché il valore effettivo è sconosciuto al momento della compilazione. Questo piano può essere buono per alcuni valori ma non ottimale per gli altri quando la query non è banale.

1

Ci sono così tante cose coinvolte nella tua domanda e tutto ha a che fare con le statistiche ..

SQL compila piano di esecuzione anche per le query Adhoc e li memorizza in cache dei piani per il riutilizzo, se sono ritenuti sicuri.

select * into test from sys.objects 

select schema_id,count(*) from test 
group by schema_id 


--schema_id 1 has 15 
--4 has 44 rows 

Prima chiedono: stiamo cercando un diverso letteralmente ogni volta, in modo da sql salva il piano, se lo ritiene come safe..You può vedere stime seconda query sono le stesse literla 4, dal momento che SQL salvato la piano per 4

--lets clear cache first--not for prod 
dbcc freeproccache 

select * from test 
where schema_id=4 

uscita:

enter image description here

select * from test where 
schema_id=1 

uscita:

enter image description here

seconda chiedono:
Passando variabile locale come param, consente di utilizzare lo stesso valore di 4

--lets pass 4 which we know has 44 rows,estimates are 44 whem we used literals 
declare @id int 
set @id=4 
select * from test 

Come potete vedere qui sotto screenshot , utilizzando le variabili locali stimata in meno di circa 29.5 righe che ha a che fare con le statistiche S ..

uscita:

enter image description here

Quindi, in sintesi, le statistiche sono cruciali nella scelta di piano di query (cicli annidati o fare una scansione o cercare) , dagli esempi, si può vedere come le stime sono diverso per ogni metodo.altre da un piano cache bloat perspective

Si potrebbe anche chiedere, cosa succede se passo molte query ad hoc, poiché SQL genera un nuovo piano per la stessa query anche se c'è un cambiamento nello spazio, di seguito sono riportati i link che vi aiuterà a

Approfondimenti:
http://www.sqlskills.com/blogs/kimberly/plan-cache-adhoc-workloads-and-clearing-the-single-use-plan-cache-bloat/
http://sqlperformance.com/2012/11/t-sql-queries/ten-common-threats-to-execution-plan-quality