use*_*552 5 sql t-sql sql-server sql-server-2005
我们最近遇到了性能问题,并且通过执行DBCC freeproccache解决了这个问题......现在,我们还有很多问题要回答;
任何帮助表示赞赏!
你的问题到处都是,所以我会尽力解决这些问题.过程缓存只是如此之大.您的过程高速缓存可能已经填充了一次性计划(这对统计信息没有影响,但统计信息可能会影响计划高速缓存).您可以在Kimberly Tripp的博客文章" 为特定工作负载计划缓存和优化 "中阅读有关一次性计划的大量详细信息- 包括针对sys.dm_exec_cached_plans的查询,这将有助于确定缓存何时填充了大量单个 -使用计划.正如她所建议的那样,您可以通过对ad hoc工作负载使用optimize来防止这种膨胀.如果你发现需要经常这样做,我会说安排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;
Run Code Online (Sandbox Code Playgroud)
现在您需要确认您确实要清除此计划.例如,如果您将该查询视为CEO明天可能会执行的操作,那么最好将其留在那里.如果要清除计划,可以直接清除它:
DBCC FREEPROCCACHE([paste plan handle from above query here]);
Run Code Online (Sandbox Code Playgroud)
这听起来比在DBCC FREEPROCCACHE全球范围内运行要多得多,但如果你在缓存中有很多好的计划,对你的整体用户来说肯定会更好.
不过,这听起来像是一个创可贴.如果您的缓存充满了垃圾,并且性能进入厕所,直到您释放缓存,您需要在架构中查看更高级别,如何提交查询等.这是我期望的行为LINQ2SQL的第一次迭代,它会为每个不同长度的字符串参数缓存查询计划的版本.因此,如果你有一个参数'1月',你会得到一个不同于'2月'参数的计划,因为它会将数据类型定义为VARCHAR(7)vs VARCHAR(8)..很确定这种行为是固定的,但我对你的环境/应用程序知之甚少,无法建议准确地寻找"糟糕的想法".