带case语句的SQL查询性能

时间:2019-04-22 19:35:51

标签: sql sql-server tsql

我有一个简单的选择,运行速度非常慢,并将其范围缩小到一个特定的where语句。

我不确定您是否需要查看整个查询,或者也许能够帮助我理解为什么此案对性能的影响如此之大。我觉得自己找到了问题,但似乎无法解决。我以前曾处理过案例陈述,但从未遇到过如此巨大的性能问题。

对于此特定示例。声明如下:Declare @lastInvOnly as int = 0

随后出现问题where语句,并运行了大约20秒钟:

 and ird.inventorydate = case when @lastinvonly=0 then  --get the last reported inventory in respect to the specified parameter
        (select max(ird2.inventorydate)    from irdate ird2
                where ird2.ris =r.ris and ird2.generateddata!='g'and ird2.inventorydate <= @inventorydate)
            end

删除case使其在1秒钟内运行,这是一个巨大的差异。我不明白为什么。

and ird.inventorydate = 
            (select max(ird2.inventorydate)    from irdate ird2
                    where ird2.ris =r.ris and ird2.generateddata!='g'and ird2.inventorydate <= @inventorydate)

2 个答案:

答案 0 :(得分:1)

几乎可以肯定它应该是派生表,而应该加入它。子选择的性能往往很差,有条件使用时甚至更糟。尝试以下方法:

INNER JOIN (
   select
       ris
      ,max(inventorydate) AS [MaxInvDate]
   from irdate
   where s and generateddata!='g'
   and inventorydate <= @inventorydate
   GROUP BY ris
) AS MaxInvDate ON MaxInvDate.ris=r.ris
and ird.inventorydate=MaxInvDate.MaxInvDate
and @lastinvonly=0

我不是100%肯定的说,这在逻辑上适用于整个查询,因为您的问题只占一小部分。

答案 1 :(得分:0)

我无法确定是否没有执行计划,但是过滤器中的分支可能是导致性能问题的原因。从理论上讲,优化器可以采用不带大小写的版本,并应用优化以将过滤器中的子查询转换为联接。添加case语句后,将无法再进行优化,并且将对每一行执行子查询。可以重构代码以帮助优化器完成工作,如下所示:

outer apply (
    select max(ird2.inventorydate) as maxinventorydate
    from irdate ird2
    where ird2.ris = r.ris
      and ird2.generateddata <> 'g'
      and ird2.inventorydate <= @inventorydate
      and @lastinvonly = 0
) as ird2
where ird.inventorydate = ird2.maxinventorydate