我们有一个.net winforms应用程序通过.net Web服务访问SQL Server 2008数据库。有时我们的应用程序行为非常慢,但在重新启动SQL Server服务后,应用程序的执行速度会快得多。
我们确实有自动预定作业,每晚运行以使用以下命令清除缓冲区和过程缓存。
DBCC FREEPROCCACHE,
DBCC DROPCLEANBUFFERS
任何人都可以确认运行上面的命令实际上会降低查询性能,我们应该摆脱它吗?
为什么SQL Server重启后应用程序的运行速度相对较快?
感谢您的帮助。
编辑: 我们在这里看几个线程,发现临时表可能是这里的问题。 当sql server在重新启动时摆脱所有临时表,因此行为更快。临时表究竟是什么?我们在查询中的许多地方选择#tables。这些临时表是否可以在程序本身中执行某些操作,以便在不需要时删除临时表。
感谢。
答案 0 :(得分:8)
既然你问“为什么”,我会给你完整的答案:)
定期运行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';
因此,您从示例中看到,如果您的性能因为调用DBCC FREEPROCCACHE
而增加,则很可能是因为您为应用提供了机会以获得不同的查询在下次运行时为您的查询做好计划。再一次 - 只是偶然或巧合,你的应用程序会变得更快(或更慢)。
就DBCC DROPCLEANBUFFERS
而言,定期运行此操作几乎总是会降低您的应用程序速度。此命令强制查询转到存储子系统,而不是从内存中读取缓存的页面。我认为这可能有助于提高性能的唯一方法是,如果您的数据库服务器的内存配置不正确,并且它正在交换到页面文件,因为它超出了物理内存。
那么解决方案是什么?
解决方案是不寻找一般原因或创可贴。您将需要使用SQL Server探查器运行一些性能较差的查询,并识别出有问题的各个查询。您将不得不对这些查询进行一些“细节”分析并真正理解它们。您将需要找出是否需要在逐个查询的基础上添加,更改甚至删除索引,并且您将需要识别可能需要重写的有问题的查询。
答案 1 :(得分:4)
运行DBCC FREEPROCCACHE
和DBCC DROPCLEANBUFFERS
将刷新SQL Server进程已建立的缓存。
这可能是一件坏事 - 您丢失了所有存储的执行计划,这意味着,现在必须对每个出现的查询进行评估,解析,并且必须确定它的执行计划 - 这将在每次第一次减慢时执行每个查询。
这也是一件好事 - 它为SQL Server提供了清理机会,摆脱了可能会降低系统性能的大缓冲区。
你有没有机会关闭这个夜间程序一两个星期,看看你的应用程序在关闭时表现得更好?