我们有一个.net winforms应用程序通过.net Web服务访问SQL Server 2008数据库.有时我们的应用程序行为非常慢,但在重新启动SQL Server服务后,应用程序的执行速度会快得多.
我们确实有自动预定作业,每晚运行以使用以下命令清除缓冲区和过程缓存.
DBCC FREEPROCCACHE,
DBCC DROPCLEANBUFFERS
Run Code Online (Sandbox Code Playgroud)
任何人都可以确认运行上面的命令实际上可以减慢查询性能,我们应该摆脱它吗?
SQL Server重新启动后,为什么应用程序运行速度相对较快?
谢谢您的帮助.
编辑:我们在这里看几个线程,发现临时表可能是这里的问题.当sql server在重新启动时摆脱所有临时表,因此行为更快.临时表究竟是什么?我们在查询中的许多地方选择#tables.这些临时表是否可以在程序本身中执行某些操作,以便在不需要时删除临时表.
谢谢.
既然你问"为什么",我会给你完整的答案:)
运行DBCC FREEPROCCACHE
和DBCC DROPCLEANBUFFERS
基于周期是不是一个有效的解决您的问题.就像重新开始一样,如果它改善了任何东西,那只是巧合,你可能会看到不稳定的结果.完全可能的是,如果这个"修复"纠正了你的性能问题,它将在未来看似随机而且比你现在看到的更严重.
运行时DBCC FREEPROCCACHE
,SQL Server将重新编译它们下次运行时的每个存储过程或缓存查询计划.如果事实证明SQL Server在后续运行中选择了更适合一般操作的计划,那么通常会看到性能提升.如果SQL Server选择通常性能较差的计划,您将看到性能下降.为什么会选择一个通常更糟糕的计划?嗯,这取决于第一个执行的查询 - SQL Server将根据传递的参数的选择性为语句选择一个计划.看看这个例子:
SET NOCOUNT ON;
IF OBJECT_ID('temporary_demo') IS NOT NULL DROP TABLE temporary_demo;
IF OBJECT_ID('temporary_demoproc') IS NOT NULL DROP PROC temporary_demoproc;
GO
CREATE TABLE temporary_demo (id int primary key identity(1,1), id2 int, txtval nvarchar(100));
insert temporary_demo (id2, txtval) values (1, 'something highly selective');
declare @i int;
set @i = 1;
while @i < 10000 begin
insert temporary_demo (id2, txtval) select 2, 'something else ';
set @i = @i + 1;
end
insert temporary_demo (id2, txtval) select 2, 'needle in a haystack';
create index ix_id2 on temporary_demo(id2);
GO
create proc temporary_demoproc @searchid int, @searchtxtval nvarchar(100) as
select * from temporary_demo where id2 = @searchid and txtval = @searchtxtval;
GO
--Look at the query plans for both of these procedures.
--Note that the plan chosen depends on which one is called first.
exec temporary_demoproc 1, 'something highly selective';
exec temporary_demoproc 2, 'needle in a haystack';
dbcc freeproccache;
exec temporary_demoproc 2, 'needle in a haystack';
exec temporary_demoproc 1, 'something highly selective';
Run Code Online (Sandbox Code Playgroud)
因此,从示例中可以看出,如果您的性能因为调用而增加DBCC FREEPROCCACHE
,那么很可能是因为您为应用程序提供了在下次运行时为您的查询获取不同查询计划的机会.再一次 - 只是偶然或巧合,你的应用程序会变得更快(或更慢).
到目前为止DBCC DROPCLEANBUFFERS
,定期运行这几乎总会减慢您的应用程序.此命令强制查询转到存储子系统,而不是从内存中读取缓存的页面.我可以想到这可能有助于提高性能的唯一方法是,如果您的数据库服务器的内存配置不正确,并且它正在交换到页面文件,因为它超出了物理内存.
那么解决方案是什么?
解决方案是不寻找一般原因或创可贴.您将需要使用SQL Server探查器运行一些性能较差的查询,并识别出有问题的各个查询.您将不得不对这些查询进行一些"细节"分析并真正理解它们.您将需要确定是否需要逐个查询地添加,更改甚至删除索引,并且您将需要识别可能需要重写的有问题的查询.
运行DBCC FREEPROCCACHE
并将DBCC DROPCLEANBUFFERS
刷新 SQL Server 进程已建立的缓存。
这可能是一件坏事 - 您丢失了所有存储的执行计划,这意味着,现在必须评估、解析出现的每个查询,并且必须确定它的执行计划 - 这将减慢每个查询的第一次执行速度询问。
这也可能是一件好事 - 它为 SQL Server 提供了清理的机会,以摆脱可能会降低系统性能的大缓冲区。
您是否有机会关闭此夜间程序一两周,并观察关闭此程序后您的应用程序是否表现更好?