2011-08-19 1 views
5

Recentemente abbiamo avuto un problema di prestazioni e questo è stato risolto eseguendo il freeproccache di DBCC ... Ora abbiamo molte più domande a cui rispondere;DBCC freeproccache?

  • Che cosa ha reso obsoleta la procedura?
  • Se indici o statistiche non aggiornati, perché la query non è stata ricompilata da sola?
  • È buona pratica pianificare DBCC freeproccache come lavoro?
  • C'è un modo per identificare potenziali piani di query obsoleti?
  • C'è un modo per identificare una query offendente?

Qualsiasi aiuto è apprezzato!

+0

Identificare la versione di SQL Server che si sta utilizzando, ad es. [tag: sql-server-2005], [tag: sql-server-2008] ... –

+2

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. –

+0

Sono su SQL Server 2005! – user173552

risposta

8

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".

+0

Ignora ottimizzazione per carichi di lavoro ad hoc: è stato introdotto con SQL Server 2008. –