2011-01-29 73 views
0

我們的數據庫中有一個函數,用於搜索兩個大表來查看是否存在值。這是一個相當大的查詢,但它被優化爲使用索引,並且運行速度非常快。SQL Server函數間歇性性能問題

在過去的兩週裏,這個功能決定了三次失靈,運行速度非常慢,從而導致死鎖和性能不佳。即使在使用量不足的情況下也會發生這種情況。

在SQL Server中使用「更改函數」重建函數似乎解決了這個問題。一旦我們這樣做,服務器的使用恢復正常,一切正常。

這導致我們認爲函數查詢計劃已經重建,並且考慮了正確的索引,但是我們不知道爲什麼SQL Server決定突然改變查詢計劃到更糟糕的計劃。

有沒有人有任何想法可能會導致這種行爲,或如何測試它,或防止它?我們正在運行SQL Server 2008 Enterprise。

+1

我們可能需要更多信息。它是什麼類型的函數(標量,表值或內聯)?它運行的表格有哪些結構?哪些索引可用,以及您期望它使用哪些索引?它開始表現不好時究竟做了什麼? – 2011-01-29 00:31:28

回答

5

您描述的行爲通常是由於緩存不正確的查詢計劃和/或過期的統計信息。

當你在WHERE子句,尤其是那些形式的一長串大量的參數,它通常發生:

(@parameter1 is NULL OR TableColumn1 = @parameter1) 

說,緩存的查詢計劃的到期,和proc被稱爲一個非代表性的一組參數。然後該計劃被緩存用於該數據配置文件。但是,如果程序更常用於一組非常不同的參數,則該計劃可能不合適。這通常被稱爲「參數嗅探」。

有一些方法可以減輕和消除此問題,但它們可能涉及權衡並取決於您的SQL Server版本。看看OPTIMIZE FOROPTIMIZE FOR UNKNOWN。如果(如果)這個過程不經常被調用,但必須儘可能快地運行,你可以將它標記爲OPTION(RECOMPILE),每次調用它時強制重新編譯,但不要爲頻繁調用的過程執行此操作,或者在沒有調查的情況下。

[注:知道哪些Service pack and Cumulative Update (CU)您的SQL Server 2008框有,因爲重新編譯和參數嗅探邏輯在一些版本的工作方式不同]

運行此查詢(由格倫·貝瑞),以確定國家統計:

-- When were Statistics last updated on all indexes? 
SELECT o.name, i.name AS [Index Name], 
     STATS_DATE(i.[object_id], i.index_id) AS [Statistics Date], 
     s.auto_created, s.no_recompute, s.user_created, st.row_count 
FROM sys.objects AS o WITH (NOLOCK) 
INNER JOIN sys.indexes AS i WITH (NOLOCK) 
ON o.[object_id] = i.[object_id] 
INNER JOIN sys.stats AS s WITH (NOLOCK) 
ON i.[object_id] = s.[object_id] 
AND i.index_id = s.stats_id 
INNER JOIN sys.dm_db_partition_stats AS st WITH (NOLOCK) 
ON o.[object_id] = st.[object_id] 
AND i.[index_id] = st.[index_id] 
WHERE o.[type] = 'U' 
ORDER BY STATS_DATE(i.[object_id], i.index_id) ASC OPTION (RECOMPILE); 
+0

我同意這聽起來像參數嗅探。過時的統計數據似乎不符合事實,但如果統計數據不好,那麼通過「Alter Function」重新編譯計劃不能解決問題。 – 2011-01-29 00:53:36