2012-07-17 80 views
1

這是我遇到的問題。我查詢的表格有1.7億行。我編寫了一個存儲過程來對錶中的最新條目進行簡單查詢。當我用這樣的硬編碼字符串寫WHERE子句時:DATEADD在存儲過程的WHERE子句中的神祕行爲

SELECT top 500 a.field1 , a.field2, a.field3 
FROM database..hugeTable a(nolock) 
WHERE a.StartTime > '2012-07-17 10:10:35.477' 

它非常快。不到一秒鐘。 StartTime位於非聚集索引中。

不過,我真正想要的是這樣的:

DECLARE @fifteenMinutesAgo datetime; 
SET @fifteenMinutesAgo = DATEADD(n , -15 , GETDATE()); 

SELECT top 500 a.field1 , a.field2, a.field3 
FROM database..hugeTable a(nolock) 
WHERE a.StartTime > @fifteenMinutesAgo 

的問題是,當我運行第二個查詢,它需要近3分鐘!

所以我開始亂搞,瘋狂搜索。我認爲這可能是一個數據類型問題,所以我嘗試了各種CAST和CONVERT,但沒有成功。我嘗試使用OPTIMIZE FOR,但意識到它不適用於此版本的SQL。我檢查了StartTime的數據類型;它是類型datetime

,我試過了,這是非常奇怪的另一件事,是這樣的:

DECLARE @fifteenDaysAgo datetime; 
SET @fifteenDaysAgo = DATEADD(d , -15 , GETDATE()); 

SELECT top 500 a.field1 , a.field2, a.field3 
FROM database..hugeTable a(nolock) 
WHERE a.StartTime > @fifteenDaysAgo 

我改變了它從搜索的最後15分鐘,最後15天。神奇的是它又快又快了!不到一秒鐘。

這使我相信,SQL以某種方式難以比較時間?它不需要查看datetimeTIME部分以查看它是否符合比較聲明?我不知道。我在這裏抓着吸管。

所以我的問題是,我怎樣才能使這合理快速,仍然保持我的@fifteenMinutesAgo動態?

+1

您是否查看了兩次查詢之間的執行計劃,以查看執行中可能存在的差異? – LittleBobbyTables 2012-07-17 16:31:02

+0

我應該包括那個。是的,執行計劃是相同的。 – davehale23 2012-07-17 16:33:35

+3

您可以嘗試執行存儲過程'WITH RECOMPILE'選項的緩慢版本並查看是否有幫助? – a1ex07 2012-07-17 16:37:59

回答

2

看起來你的程序存在「parameter sniffing」問題。 WITH RECOMPILE選項應該有幫助

+0

正如我在問題的評論中所說的,我真的認爲這是問題所在。但是,由於閱讀您鏈接的文章,我意識到這不是問題。我沒有使用參數,我正在使用變量。但是,不知何故,在我的SP中加入'WITH RECOMPILE'使它快速一段時間。我只是按照我的確切步驟CTRL-Z回來,以確保我正確運行它,並且在測試您的建議時,我不會以某種方式將硬編碼日期留在那裏。任何其他想法? – davehale23 2012-07-17 19:01:27

+0

如果它不時有幫助,我會懷疑統計信息沒有被正確更新,並且優化器使用錯誤的執行計劃。我不熟悉SQLServer 2000;在2005年和2008年,你可以強制查詢使用特定的執行計劃,不知道2000年是否有這樣的選擇... – a1ex07 2012-07-17 19:25:45

+0

另一個建議:如果您在存儲過程的主體中使用條件,那麼您也有可能會遇到與參數嗅探非常相似的問題 - 首次執行時創建的過程編譯和執行計劃,然後重新使用相同的計劃。 – a1ex07 2012-07-17 19:44:33