2011-05-31 122 views
11

我有一個表[MyTable]與列[MyColumn] NVarchar(50)。我有此列非聚集索引,現在在運行以下兩個查詢:索引搜索與合併

SELECT 1 
FROM [MyTable] M 
WHERE M.[MyColumn] = @MyColumn 

SELECT 1 
FROM [MyTable] M 
WHERE M.[MyColumn] = COALESCE(@MyColumn, M.[MyColumn]) 

我首先注意到的查詢使用索引查找(非聚集),第二個是使用索引掃描(非集羣)。我可以知道我將如何使用索引搜索與coalesce或isnull?

回答

2

可我知道我將如何利用 指數與聚結尋求或ISNULL?

也許不是你的問題的答案,但你可以有兩個不同的查詢。其中一個用於@MyColumn is null,另一個用於where子句中要使用@MyColumn的情況。

IF @MyColumn IS NULL 
BEGIN 
    SELECT 1 
    FROM [MyTable] M 
END 
ELSE 
BEGIN 
    SELECT 1 
    FROM [MyTable] M 
    WHERE M.[MyColumn] = @MyColumn 
END 
0

使用功能,如在COALESCEISNULL where子句要求服務器搜索結果的那些功能 - 直到他們在結果集的每一行執行哪些是未知的,所以沒有辦法它使用索引。

要充分利用索引,請不要使用WHERE子句中的函數,可以使用標準條件對其進行修改。 WHERE MyColumn = @MyColumn OR @MyColumn IS NULL

+2

只有'MyColumn = @MyColumn或@MyColumn IS NULL'也會導致索引掃描。 ;-) – Tomalak 2011-05-31 11:46:01

+0

我運行了「MyColumn = @MyColumn或@MyColumn IS NULL」,但它也使用了索引掃描(非集羣) – 2011-05-31 11:55:36

+0

'OR'不會短路,它將檢查每一行。如果優化器知道它需要檢查每一行,那麼只需要掃描。 – JNK 2011-05-31 12:09:35

0

這並不容易,因爲Alex指出使用函數強制掃描,因爲優化器知道它需要檢查每一行。

你可以做的是創建一個Computed Column你的函數的結果,and index that column

有沒有一個真正的更漂亮的方式來尋求。

編輯:

在重讀你的問題,除非你重新考慮你的邏輯,這可能不是一個選擇。你正在將一個變量集成到函數中,並且絕對沒有辦法對它進行索引。

編輯2:

而不是當前的邏輯,你可以試試:

... 
WHERE (M.[MyColumn] = @MyColumn 
     OR @MyColumn IS NULL) 
0

我想你會在一個更復雜的一個使用此查詢,可能與EXISTS

EXISTS 
(SELECT 1 
    FROM [MyTable] M 
    WHERE M.[MyColumn] = COALESCE(@MyColumn, M.[MyColumn]) 
) 

試試這個:

EXISTS 
(SELECT 1 
    FROM [MyTable] M 
    WHERE M.[MyColumn] = @MyColumn 
) 
OR EXISTS 
(SELECT 1 
    FROM [MyTable] M 
    WHERE @MyColumn IS NULL 
) 

或者這一個:

CASE WHEN @MyColumn IS NULL 
    THEN 1 
    ELSE 
     (SELECT 1 
      FROM [MyTable] M 
      WHERE M.[MyColumn] = @MyColumn 
     ) 
END 
0

在使用coalesce子句的查詢中,優化器知道「MyColumn」是一個值範圍,因此它將決定在索引上使用掃描。當傳入一個非null變量時,唯一使用seek的方法是編寫兩個存儲過程並通過變量的邏輯測試調用合適的變量。

如果你有一個情況一樣簡單的例子,你想使用索引查找當變量是NOT NULL,那麼你應該爲代碼中的查詢:

If @MyColumn is NULL 
Begin 
    EXEC MyStoredProcWithMyColumn=Mycolumn 
END 
ELSE 
Begin 
    EXEC MyStoredProcWithMyColumn=Variable @MyColumn 
END 

創建兩個存儲的過程之一後使用where子句與變量返回數據,另一個與列的where Cluase等於自身。