2009-09-18 80 views
6

我有一本條款加入在存儲過程中我繼承:T-SQL ISNULL()優化

WHERE a.is_active = 1 
AND b.due_date <= ISNULL(@due_date_limit, b.due_date) 

如何將我重新寫這個刪除ISNULL因爲它導致嚴重的性能問題?

+0

SQL Server版本? – AnthonyWJones 2009-09-18 14:11:51

回答

7

,我將有一個if語句,檢查@due_date_limit

IF (@due_date_limit IS NULL) 
BEGIN 
    ... 
    WHERE a.is_active = 1 --not required to compare b.due_date <= b.due_date 
END 
ELSE 
BEGIN 
    ... 
    WHERE a.is_active = 1 
    AND  b.due_date <= @due_date_limit 
END 
2
AND @due_date_limit IS NULL OR b.due_date <= @due_date_limit 

,但我不敢肯定這將是快得多。

在這種情況下
+0

如果存在索引。 – recursive 2009-09-18 14:19:24

+0

指數不是一個問題 - 即使存在,該指數也只會在下半年使用。這遠比ISNULL/COALESCE建議好。 – 2009-09-18 14:39:31

1

@due_date_limit是一個存儲過程變量,因此可以在此查詢中提取出來一起:

if (@due_date_limit is NULL) 
    <run query that works when @due_date_limit is NULL> 
else 
    <run query that works when @due_date_limit is NOT NULL> 
1
COALESCE(@due_date_limit, b.due_date) 

可能會幫助

+0

這會優雅地處理事情,但執行1 = 1的等價物是一種浪費。 – 2009-09-18 14:33:44

2

是否有due_Date上的索引?如果不添加一個,然後檢查性能。如果已經存在,則更改爲兩個單獨的語句

If @due_date_limit is null 
    Select [stuff] 
    From Table 
    Else 
    Select [stuff] 
    From Table 
    Where b.due_date <= @due_date_limit 

但意識到不能過濾(當@due_date_limit爲空),或使用<過濾=有可能返回的記錄相當數量,這將消除任何機會使用索引並需要完整的表掃描。這可能是你正在經歷的。

3

這種類型的查詢性能低下的最常見原因是,優化程序無法確定@due_date_limit對大多數查詢的典型值。通常,由後續執行生成並重新使用的計劃有利於值爲空的情況。

由於SQL 2005,你可以使用指導優化器的「優化」選項: -

WHERE a.is_active = 1 
AND b.due_date <= ISNULL(@due_date_limit, b.due_date) 
OPTION (OPTIMIZE FOR (@due_date_limit = '09/01/2009')) 
+0

如果該參數爲空,爲什麼仍要比較值?你不這樣做,所以不要使用ISNULL/COALESCE作爲可選參數。 – 2009-09-18 14:40:57

0

由於@due_date_limit是一個存儲過程的變量,你可以檢查它的NULL查詢之前,並將其設置到需要的默認值,從而消除WHERE條款中的ISNULL檢查。

IF (@due_date_limit IS NULL) 
BEGIN 
    SET @due_date_limit = '09/01/2009'; 
END 

,然後你WHERE條款只會是這樣的:

WHERE a.is_active = 1 
AND b.due_date <= @due_date_limit 
+0

如果你需要它與列記錄相同以滿足'<='操作符條件,那麼astander的答案是一個更好的解決方案,否則設置如果在這樣的查詢之前,因爲它會更快並且沒有檢查。 – johntrepreneur 2013-07-08 01:29:16