Le vostre domande sono dappertutto, quindi cercherò di affrontarle tutte. La cache della procedura è solo così grande. La cache della procedura potrebbe essere stata riempita con piani monouso (questo non ha alcun impatto sulle statistiche, anche se le statistiche possono influire sulla cache del piano). È possibile leggere molti dettagli sui piani monouso nel post del blog di Kimberly Tripp "Plan cache and optimizing for adhoc workloads", inclusa una query su sys.dm_exec_cached_plans che consentirà di identificare quando la cache è popolata da molti piani monouso. Come suggerisce, è possibile evitare questo gonfiore utilizzando l'ottimizzazione per carichi di lavoro ad hoc. Se si trova la necessità di farlo spesso, direi che la programmazione di freeproccache come lavoro è un cerotto, non una soluzione.
Per eliminare un piano "cattivo", è necessario innanzitutto identificare il piano "cattivo". Potrebbe trattarsi di un piano che supera una certa dimensione e/o che non è stato eseguito in un dato momento, o che è stato identificato da una query di lunga durata, ecc. Sfortunatamente non è semplice identificare un piano vittima di un parametro sniffing se non conosci già la query o le query che sono interessate. Supponiamo che si desidera trovare i piani più antichi nella cache che non è stato eseguito in più di una settimana:
;WITH x AS
(
SELECT TOP 10
qs.[sql_handle], qs.plan_handle,
txs = qs.statement_start_offset,
txe = qs.statement_end_offset,
[size] = cp.size_in_bytes,
[uses] = SUM(cp.usecounts),
[last] = MAX(qs.last_execution_time)
FROM
sys.dm_exec_query_stats AS qs
INNER JOIN
sys.dm_exec_cached_plans AS cp
ON qs.plan_handle = cp.plan_handle
WHERE
qs.last_execution_time < DATEADD(DAY, -7, CURRENT_TIMESTAMP)
GROUP BY
qs.[sql_handle], qs.plan_handle, cp.size_in_bytes,
qs.statement_start_offset, qs.statement_end_offset
ORDER BY
[size] DESC
)
SELECT
x.plan_handle,
size, uses, [last],
[statement] = COALESCE(NULLIF(
SUBSTRING(t.[text], x.txs/2,
CASE WHEN x.txe = -1 THEN 0 ELSE (x.txe - x.txs)/2 END
), ''), t.[text])
FROM x
CROSS APPLY sys.dm_exec_sql_text(x.[sql_handle]) AS t;
Ora è necessario verificare che si vuole veramente cancellare questo piano. Ad esempio, se riconosci la query come qualcosa che il CEO potrebbe eseguire domani, forse è meglio lasciarla lì. Se si desidera cancellare il piano, è possibile cancellare direttamente dicendo:
DBCC FREEPROCCACHE([paste plan handle from above query here]);
Questo suona come molto più lavoro che correre DBCC FREEPROCCACHE
a livello globale, ma se avete un sacco di buoni piani nella cache, sarà sicuramente migliore per gli utenti in generale.
Ancora, questo suona davvero come un cerotto. Se la cache si sta riempiendo di cianfrusaglie e le prestazioni vanno in bagno finché non si libera la cache, è necessario osservare un livello superiore nell'architettura, come vengono inviate le query, ecc. Questo è il comportamento che mi aspetto dai prima iterazione di LINQ2SQL, in cui memorizzava nella cache una versione di un piano per una query per ogni argomento stringa di lunghezza diversa. Pertanto, se avessi un parametro di "gennaio", otterresti un piano diverso rispetto a un parametro di "febbraio" perché definirà il tipo di dati come VARCHAR(7)
rispetto a VARCHAR(8)
. Abbastanza sicuro che il comportamento sia corretto ma non conosco abbastanza il tuo ambiente/applicazione per suggerire dove cercare esattamente le "idee sbagliate".
Identificare la versione di SQL Server che si sta utilizzando, ad es. [tag: sql-server-2005], [tag: sql-server-2008] ... –
Tutto 'DBCC freeproccache' fa svuotare la cache delle procedure. Non farà aggiornare le statistiche. Al contrario, se le statistiche vengono aggiornate automaticamente, il piano verrà ricompilato.Presumo che tu abbia avuto un problema di sniffing dei parametri in cui il piano che era nella cache per una query non era adatto a tutti i possibili valori dei parametri. –
Sono su SQL Server 2005! – user173552