2011-05-18 126 views
5

我有一個存儲過程,需要一秒鐘才能正常運行。用戶需要來自該查詢中另一個表的數據,因此我將這些數據與UNION ALL以及新表中缺少的一些虛擬列合併。SQL 2000 UNION ALL遺失查詢優化

它在測試中工作正常,但是當我們將它部署到SQL 2000 Server時,它開始超時。舊的查詢在一秒之內運行,兩個新的查詢都在一秒之內運行,但是當它們使用UNION ALL組合時,查詢超時。

下面是查詢外觀的一般概念。真正的查詢有大約20個輸入參數和返回大約30或40列,但是這應該瞭解基本的概念:

CREATE PROCEDURE dbo.SearchHistory 
(
    @Criteria1 bigint, 
    @Criteria2 int, 
    @Criteria3 varchar(10) 
) 
AS 
BEGIN 
    -- Part 1 
    SELECT 
     A, 
     NULL AS B, 
     0 AS C, 
     D 
    FROM TableA 
    WHERE @Criteria1 IS NULL 
    AND @Criteria3 IS NULL 
    AND (A = @Criteria2 OR @Criteria2 IS NULL) 

UNION ALL 

    -- Part 2 
    SELECT 
     A, 
     NULL AS B, 
     0 AS C, 
     E 
    FROM TableA 
    WHERE @Criteria1 IS NULL 
    AND @Criteria3 IS NULL 
    AND (A = @Criteria2 OR @Criteria2 IS NULL) 

UNION ALL 

    -- Part 3 
    SELECT 
     A, 
     B, 
     C, 
     D 
    FROM TableB 
    WHERE (F = @Criteria1 OR @Criteria1 IS NULL) 
    AND (A = @Criteria2 OR @Criteria2 IS NULL) 
    AND (G = @Criteria3 OR @Criteria3 IS NULL) 
END 

在上面的例子中,@標準1不爲空,所以第1和第2將返回0行,第3部分只返回3行。但如果我評論第一部分和第二部分,它會立即結束;如果我讓他們進來,我會暫停。

你如何說服SQL Server在這種情況下不要搞亂它的執行計劃?

+0

它給你'UNION ALL'的執行計劃是什麼?還有,如果你只是在3個單獨的語句中插入一個'@ table_variable',並從最後選擇一個呢? – 2011-05-18 22:23:17

+0

(我認爲在選擇列表中缺少所需逗號的語法錯誤;這是實際代碼嗎?) – 2011-05-18 22:26:28

+0

是否將該過程更改爲CREATE PROCEDURE dbo.SearchHistory WITH RECOMPILE(...'help? – 2011-05-18 22:36:08

回答

3

我認爲你的問題是由於SQL Server的參數嗅探。

http://elegantcode.com/2008/05/17/sql-parameter-sniffing-and-what-to-do-about-it/

http://blogs.msdn.com/b/queryoptteam/archive/2006/03/31/565991.aspx

我所遇到一個好幾次。有幾種方法。例如。像@Biff MaGriff建議的那樣使用WITH RECOMPILE。我發現要解決的最簡單的方法是將所有輸入參數轉換爲本地參數,並使用本地參數。

+0

WITH RECOMPILE使所有的查詢超時,而不僅僅是@ Criteria1是非NULL。我還沒有到處嘗試局部變量,太多的其他東西正在進行,但我仍然打算嘗試它。 – 2011-05-24 19:51:55

0

如果沒有看到執行計劃,請不要回答(請將它們作爲圖像發佈,每個部分一個,聯合查詢一個)。解決方法是使用臨時表,在其中單獨插入零件。然而,更好的解決方案是首先解決查詢問題。