2011-08-19 26 views
5

我們最近出現了一個性能問題,通過執行DBCC freeproccache解決了這個問題......現在,我們有更多的問題要回答;DBCC freeproccache?

  • 什麼讓過程緩存過期?
  • 如果索引或統計數據過期,爲什麼查詢沒有 重新編譯自己?
  • 將DBCC freeproccache安排爲JOB是否是一種很好的做法?
  • 有沒有一種方法來識別潛在的過期查詢計劃?
  • 有沒有一種方法來識別有問題的查詢?

任何幫助表示讚賞!

+0

請確定您正在使用的SQL Server版本,例如[tag:sql-server-2005],[tag:sql-server-2008] ... –

+2

所有'DBCC freeproccache'確實都是空的過程緩存。它不會導致統計數據更新。相反,如果統計數據得到自動更新,那麼計劃將被重新編譯。我假設你有一個參數嗅探問題,查詢緩存中的計劃不適合所有可能的參數值。 –

+0

我在SQL Server 2005上! – user173552

回答

8

你的問題到處都是,所以我會盡力解決所有問題。過程緩存只有這麼大。您的過程緩存可能已被填充了單次使用計劃(這對統計數據沒有影響,但統計數據可能會影響計劃緩存)。您可以在Kimberly Tripp的博客文章「Plan cache and optimizing for adhoc workloads」中閱讀關於一次性使用計劃的大量詳細信息 - 包括對sys.dm_exec_cached_plans的查詢,這將有助於確定緩存中何時填充大量一次性計劃。正如她所建議的那樣,您可以通過針對ad hoc工作負載進行優化來阻止這種膨脹。如果您經常需要這樣做,我會說將freeproccache安排爲工作是一種創可貼,而不是解決方案。

爲了清除「壞」計劃,首先您需要確定「壞」計劃。這可能是一個超過一定規模和/或在一段時間內未執行的計劃,或者是由長時間運行的查詢等標識的。不幸的是,識別參數受害者的計劃並不容易除非您已經知道受影響的查詢或查詢,否則可以進行嗅探。讓我們假設你想找到尚未一個多星期運行緩存中最早的計劃:

;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; 

現在,你需要確認你真的想清楚了這個計劃。例如,如果您將該查詢視爲明天首席執行官可能會執行的操作,則最好將其留在那裏。如果你想清除計劃,可以說直接清除:

DBCC FREEPROCCACHE([paste plan handle from above query here]); 

這聽起來似乎比運行DBCC FREEPROCCACHE全球更多的工作,但如果你有很多良好計劃在緩存中,它肯定會對整個用戶更好。

不過,這聽起來像是一個創可貼。如果你的緩存充斥着垃圾,並且性能直到你釋放緩存,你需要在架構上查看更高的層次,查詢是如何提交的等等。這是我期望從LINQ2SQL的第一次迭代,它將緩存每個字符串參數的查詢計劃版本,該版本的長度不同。所以如果你有一個'1月'的參數,你會得到一個不同於'2月'的參數的計劃,因爲它會將數據類型定義爲VARCHAR(7)VARCHAR(8)。很確定,行爲是固定的,但我對您的環境/應用程序不夠了解,無法確切知道在哪裏尋找「壞主意」。

+0

忽略對臨時工作負載的優化 - 這是在SQL Server 2008中引入的。 –