在Where子句中使用“CASE”来选择各种列损害性能

时间:2012-09-16 09:19:00

标签: sql sql-server database sql-server-2005 database-performance

我的查询需要在某些列上是动态的,这意味着我得到一个参数,根据其值我决定在Where子句中获取哪一列。我使用“CASE”表达式实现了这个请求:

(CASE @isArrivalTime WHEN 1 THEN ArrivalTime ELSE PickedupTime END) 
>= DATEADD(mi, -@TZOffsetInMins, @sTime) 
 AND (CASE @isArrivalTime WHEN 1 THEN ArrivalTime ELSE PickedupTime END) 
 < DATEADD(mi, -@TZOffsetInMins, @fTime)

如果@isArrivalTime = 1然后选择ArrivalTime列,则选择PickedupTime列。我在ArrivalTime上有一个聚簇索引,在PickedupTime上有非聚簇索引。

我注意到当我使用此查询时(使用@isArrivalTime = 1),与仅使用ArrivalTime相比,我的表现要差很多。

也许查询优化器不能使用\以这种方式正确选择索引?

我比较了执行计划时注意到当我使用CASE时,32%的时间被浪费在索引扫描上,但是当我没有使用CASE (just used ArrivalTime时`)这个索引扫描只浪费了3%。

有人知道这个的原因吗?

2 个答案:

答案 0 :(得分:2)

2之间的差异很可能是由于它必须扫描的行数不同。由于您的查询很可能是更多表之间的连接的最终结果。请记住,扫描是......它的名字是什么,扫描所有行。您可以在计划中查看估计的行数,以便提出想法。

如果在动态字段上使用过滤器(例如使用大小写),则引擎不能使用该字段的索引。在这种情况下,您最好使用动态SQL生成所需的正确sql并使用exec_sql。或者使用if语句直接查询正确的内容。

您可能会发现这对于使用动态sql非常有用,它将解释原因和方法。

http://www.sommarskog.se/dynamic_sql.html

答案 1 :(得分:0)

尝试设置日期时间边界:

declare @resSTime datetime
        ,@resFTime datetime

set @resSTime = DATEADD(mi, -@TZOffsetInMins, @sTime)
set @resFTime = DATEADD(mi, -@TZOffsetInMins, @fTime)

并尝试将案例更改为“或”

( ArrivalTime >= @resSTime 
    and ArrivalTime < @resFTime 
    and @isArrivalTime = 1 )
or ( PickedupTime >= @resSTime 
    and PickedupTime < @resFTime 
    and @isArrivalTime <> 1 )