Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Quali sono le principali differenze tra OPZIONE(OTTIMIZZA PER SCONOSCIUTO) e OPZIONE(RICIMPILA)?

Sì, lo farà.

Esistono due differenze principali tra OPTION(OPTIMIZE FOR UNKNOWN) e OPTION(RECOMPILE) come si può vedere da questa citazione da MSDN :

Quindi, le due differenze principali sono:

  1. Memorizzazione nella cache (o meno) del piano di query.

Di solito il piano di query generato viene memorizzato nella cache e riutilizzato. OPTIMIZE FOR UNKNOWN non pregiudica questa caratteristica del motore. RECOMPILE sopprime questa funzione e dice al motore di eliminare il piano e di non inserirlo nella cache.

  1. Utilizzo (o meno) dei valori dei parametri effettivi durante la generazione del piano.

Solitamente l'ottimizzatore "annusa" i valori dei parametri e utilizza questi valori durante la generazione del piano. OPTIMIZE FOR UNKNOWN sopprime questa funzione e dice al motore di trattare tutti i parametri come se i loro valori fossero sconosciuti. L'ottimizzatore ha regole ed euristiche integrate su come utilizzare le statistiche disponibili per vari criteri di filtro. Vedi Ottimizza per... Mediocre? per ulteriori dettagli. Normalmente lo sniffing dei parametri viene utilizzato alla prima esecuzione della query/stored procedure e utilizza i valori dei parametri durante la prima esecuzione. Il piano generato viene memorizzato nella cache e in seguito può essere riutilizzato.

Una cosa non ovvia da ricordare qui è che in entrambi i casi (normale senza alcun suggerimento di query e con OPTIMIZE FOR UNKNOWN suggerimento) il piano generato deve essere valido e produrre un risultato corretto per qualsiasi possibile valore del parametro. È adattato ai valori sniffati che sono stati utilizzati durante la prima esecuzione nel caso normale/senza suggerimenti; non è adattato a nessun valore specifico in OPTIMIZE FOR UNKNOWN caso, ma è ancora valido se il parametro cambia in un secondo momento in qualsiasi modo.

Questo è significativo e impedisce all'ottimizzatore di eseguire determinate trasformazioni e semplificazioni del piano.

OPTION(RECOMPILE) consente all'ottimizzatore di incorporare i valori effettivi dei parametri durante ogni corsa e l'ottimizzatore utilizza i valori effettivi dei parametri per generare un piano migliore. Non devi preoccuparti che il piano generato potrebbe non funzionare con qualche altro valore di parametro, perché il piano non verrà memorizzato nella cache e riutilizzato.

Questo effetto è visibile principalmente per le Condizioni di ricerca dinamica interrogazioni. Ad esempio:

SELECT ...
FROM T
WHERE
    (@ParamSomeID = 0)
    OR
    (
        @ParamSomeID = -1
        AND
        T.SomeID NOT IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
        )
    )
    OR
    (
        T.SomeID IN
        (
            SELECT OtherTable.SomeID
            FROM OtherTable
            WHERE OtherTable.SomeID = @ParamSomeID
        )
    )
OPTION(RECOMPILE)

Se @ParamSomeID è 0 l'ottimizzatore tratterebbe la query come se non avesse alcun WHERE clausola affatto. Il piano non menzionerebbe OtherTable affatto.

Se @ParamSomeID è -1 , il piano si unirebbe a T a OtherTable utilizzando Left Anti Semi Join e scansiona l'intera OtherTable .

Se @ParamSomeID è, diciamo, 5, il piano farebbe una ricerca dell'indice nell'indice univoco su OtherTable e leggi solo una riga da OtherTable .

Senza OPTION(RECOMPILE) questo tipo di semplificazione e trasformazione non accadrebbe.

Un altro motivo per usare OPTION(RECOMPILE) è quando la distribuzione dei dati è molto distorta. Ad esempio, hai una tabella con 1 milione di righe. Una colonna ha valore 0 in 990.000 righe e valori da 1 a 10 in 1.000 righe. Le query che filtrano su questa colonna dovrebbero avere piani diversi a seconda del valore effettivo del filtro.

In entrambi gli esempi sopra OPTIMIZE FOR UNKNOWN genererebbe un piano mediocre.