2011-05-31 133 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等于自身。