2010-10-15 86 views
2

我們有一個.net winforms應用程序通過.net Web服務訪問SQL Server 2008數據庫。偶爾我們的應用程序表現得非常慢,但是在重新啓動SQL Server服務之後,應用程序執行速度會更快。爲什麼我的SQL Server重啓時速度更快?

我們確實有自動計劃的作業每晚運行以清除緩衝區和過程緩存,並使用以下命令。

DBCC FREEPROCCACHE, 
DBCC DROPCLEANBUFFERS 

任何人都可以確認,運行上面的命令實際上可以減慢查詢性能,我們應該擺脫它嗎?

爲什麼SQL Server重新啓動後應用程序運行速度相對較快?

感謝您的幫助。

編輯: 我們在這裏看到幾個線程,發現臨時表可能是這裏的問題。 當sql server在重新啓動時擺脫所有臨時表並因此動作更快。什麼是臨時表?我們在查詢中的許多地方都選擇了#tables。是這些臨時表,並且我們可以在過程本身中執行某些操作,以在不需要時刪除臨時表。

謝謝。

+0

'偶爾'意味着什麼?你多久打一次電話?另外,這是一個高IO分貝?這可能是一個索引問題。 – ScottE 2010-10-15 10:45:08

+0

它每2-3天發生一次。是的,這是一個高IO分貝。是的,它可能是一個索引問題,但爲什麼然後它相對運行更快,當sql服務器重述。 – user476769 2010-10-15 10:55:02

+0

我也很好奇爲什麼重啓可以解決這個問題。我們在SQL Express 2008中遇到同樣的問題,並且不確定原因,但是確定重啓可以修復它,直到下一次,這可能是一天,或者只有幾個小時。 – CrazyTim 2012-12-12 03:14:03

回答

3

運行DBCC FREEPROCCACHEDBCC DROPCLEANBUFFERS將刷新SQL Server進程已建立的緩存。

這可能是一件壞事 - 你失去了所有存儲的執行計劃,這意味着每一個必須進行評估的查詢都必須進行評估和分析,並且必須確定其執行計劃 - 這會減慢每一個第一個執行每個查詢的時間。

這也是一件好事 - 它爲SQL Server提供了一個清理的機會,以擺脫可能會讓系統性能下降的大型緩衝區。

是否有任何機會可以關閉這個夜間程序一兩週,並觀察您的應用程序在關閉時是否表現更好?

+0

是的你是對的,我們也讀過這個地方,運行這2個過程可能會減慢第一次查詢性能。但我們也注意到,運行這2個命令總體上可以幫助應用程序執行得更快,所以它可以像你說的那樣擺脫大緩衝區。你認爲sql服務器在sql服務重啓時自動運行這個命令嗎? – user476769 2010-10-15 10:59:01

+0

不,爲什麼要這樣。當服務重新啓動時,它會重新啓動,所以舊服務的所有內存都會丟失。高速緩存正在進行中。也就是說,如果你的應用程序污染了緩存,那麼它就有問題。看似一些存儲過程沒有重新編譯選項,儘管它實際上是需要的。 – TomTom 2010-10-15 11:35:40

7

既然你問「爲什麼」,我要去給你完整的答案:)

定期運行DBCC FREEPROCCACHEDBCC 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分析器運行一系列性能不佳的查詢,並確定存在問題的各個查詢。你將不得不對這些查詢做一些「堅果和螺栓」分析,並真正理解它們。您需要確定是否需要在逐個查詢的基礎上添加,更改甚至刪除索引,並且您需要確定可能需要重寫的有問題的查詢。

相關問題