2010-05-04 79 views
2

問:DateTime.Now如何影響SQL Server中的查詢計劃緩存?

是否經過DateTime.Now作爲參數傳遞給一個進程防止SQL Server緩存的查詢計劃?如果是這樣,那麼Web應用錯過了巨大的性能收益?

可能的解決方案:

我想DateTime.Today.AddDays(1)將是一個可能的解決方案。它會將相同的結束日期傳遞給sql proc(每天)。用戶仍然可以獲得最新的數據。請說出這一點。

給出的例子:

比方說,我們有一個存儲過程。它將數據報告給網頁上的用戶。用戶可以設置日期範圍。如果用戶設置今天的日期作爲「截止日期」,其中包括今天的數據,Web應用程序通過DateTime.Now到SQL PROC。

假設一個用戶運行report-- 5/1/2010now --over和過幾次。在網頁上,用戶看到5/1/20105/4/2010。但Web應用程序將DateTime.Now傳遞給sql proc作爲結束日期。因此,proc中的結束日期將始終不同,儘管用戶正在查詢類似的日期範圍。

假設的表和用戶數量的記錄數量都很大。所以任何性能收益很重要。因此這個問題的重要性。

例proc和執行(如果這能幫助理解):

CREATE PROCEDURE GetFooData 
    @StartDate datetime 
    @EndDate datetime 
AS 

    SELECT * 
    FROM Foo 
    WHERE LogDate >= @StartDate 
    AND LogDate < @EndDate 

下面是使用DateTime.Now樣品執行:

EXEC GetFooData '2010-05-01', '2010-05-04 15:41:27' -- passed in DateTime.Now 

下面是使用DateTime.Today的樣品執行。 AddDays(1)

EXEC GetFooData '2010-05-01', '2010-05-05' -- passed in DateTime.Today.AddDays(1) 

相同的數據i因爲當前時間是:2010-05-04 15:41:27,所以這兩個返回都是特效。

回答

1

由於您調用的是存儲過程,而不是直接查詢,那麼您唯一更改的查詢就是您發送給SQL的實際批次,即EXEC GetFooData '2010-05-01', '2010-05-05'GetFooData '2010-05-01', '2010-05-04 15:41:27'。這是一個微不足道的批次,它會產生一個微不足道的計劃。誠然,從嚴格的技術角度來看,你失去了一些表現,這將是無法估量的。在這個迴應中解釋了爲什麼會發生這種情況的詳細信息:Dynamically created SQL vs Parameters in SQL Server

好消息是,如果您的SqlClient調用代碼發生輕微的變化,那麼即使您在那裏提到的性能提高很小,您也會受益。改變你的SqlCommand代碼是一個明確的存儲過程調用:

SqlCommand cmd = new SqlCommand("GetFooData", connection); 
cmd.CommandType = CommandType.StoredProcedure; 
cmd.Parameters.AddWithValue("@StartDate", dateFrom); 
cmd.Parameters.AddWithValue("@EndDate", DateTime.Now); 

作爲一個側面說明,存儲本地化的時間在數據庫中是不是一個很好的主意,由於客戶是在不同的時區比服務器和由於夏時制夜間變化的複雜性。一個更好的解決方案是總是存儲UTC時間,並簡單地將其格式化爲用戶在應用程序中的當地時間。

+0

感謝您的回答,@Remus。我正在處理的真正的SQL查詢很複雜;它涉及多個連接表和where子句。那麼性能增益可能是不平凡的? – 2010-05-05 01:49:51

+0

可能。運行SET STATISTICS TIME ON後,您可以在SSMS查詢窗口中運行查詢。這將打印查詢編譯時間,這將是您*可*保存的時間。還有各種性能計數器可以幫助您做出決定,請參閱http://blogs.msdn.com/sqlprogrammability/archive/2007/01/19/12-0-plan-cache-trace-events-and-performance -counters.aspx。請注意,SQL Server在自動參數化查詢方面做得相當不錯,但每次使用@parameters時都沒有發生完全相同的文本傳遞。 – 2010-05-05 03:45:34

6

查詢計劃時將忽略參數值的緩存。基本上參數保證存在一致的,可重用的查詢,因爲就SQL Server而言,它們是類型安全的。

你想要的不是查詢計劃,而是結果緩存。這會受到你描述的行爲的影響。

由於您似乎只處理整天,您可以嘗試傳入日期而不是日期時間,以儘量減少不同的參數值。也可以嘗試在應用程序中緩存查詢結果,而不是每次都進行數據庫往返。

1

就你而言,如果第二個參數只是實時向上漂移,那麼你可能沒問題。

然而,有可能成爲parameter sniffing的受害者,其中第一次執行(產生高速緩存的執行計劃)被調用,該參數產生對通常使用的其他參數(或數據配置文件發生巨大變化)。後來的調用可能會使用一個有時非常差的計劃,甚至不能正確完成。

如果您的數據配置文件因參數的不同選擇而發生急劇變化,並且某些參數選擇的執行計劃變得很差,您可以將參數隱藏到本地變量中 - 這將有效地防止SQL Server 2005中的參數嗅探。還有WITH RECOMPILE(無論是在SP還是在EXEC中 - 但對於大量調用的SP,這不是一個可行的選擇)在SQL Server 2008中,我幾乎總是使用OPTIMIZE FOR UNKNOWN,這將避免產生基於參數的計劃嗅探。

相關問題