索引寻求与合并

时间:2011-05-31 11:14:23

标签: sql-server sql-server-2005 sql-server-2008 indexing

我有一个表[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] )   

我注意到第一个查询是使用 Index Seek(NonClustered),第二个查询是使用 Index Scan(Non Clustered)。我可以知道如何利用coalesce或isnull来使用索引搜索?

5 个答案:

答案 0 :(得分:2)

  

我可以知道如何使用   索引寻求与coalesce或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  

答案 1 :(得分:0)

在where子句中使用COALESCEISNULL等函数要求服务器搜索这些函数的结果 - 这些函数在每次执行之前都是未知的结果集中的行,因此无法使用索引。

要充分利用索引,请不要使用WHERE子句中的函数,使用标准条件进行修改,例如: WHERE MyColumn = @MyColumn OR @MyColumn IS NULL

答案 2 :(得分:0)

这并不容易,因为Alex指出使用函数强制扫描,因为优化器知道它需要检查每一行。

您可以为Computed Column功能的结果and index that column创建{{3}}。

没有更好的方式来寻求。

修改

在重新阅读您的问题时,除非您重新考虑您的逻辑,否则这可能不是您的选择。您正在将一个变量集成到该函数中,并且绝对没有办法将其编入索引。

编辑2:

而不是当前的逻辑,尝试类似:

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

答案 3 :(得分: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

答案 4 :(得分:0)

在带有coalesce子句的查询中,优化器知道“MyColumn”是一系列值,因此它将决定对索引使用扫描。传入非null变量时使用搜索的唯一方法是编写两个存储过程,并通过变量的逻辑测试调用适当的过程。

如果您的情况与示例一样简单,并且您希望在变量为NOT NULL时使用Index Seek,则应将查询编码为:

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

创建两个存储过程之后,使用带有变量的where子句返回数据,使用where cluase返回数据等于自身。