SQL存储过程;使用ISNULL(db1.value,db2.value)性能问题

时间:2015-08-13 18:49:07

标签: sql sql-server performance stored-procedures

尝试调试存储过程以找出它永远不会结束的原因(等待> 2分钟)。 proc有3个左连接,然后在底部是一个ISNULL,它检查db是否为null,然后用第2个db的值替换它。我发现问题的方法是注释掉连接和子句然后慢慢地在句子中添加连接。在最后一个子句中添加后,它开始加载太长时间。 我的问题是,有没有办法解决这个不涉及索引?如果可能的话,你能解释为什么这会导致大的加载时间吗?

 FROM X x WITH (NOLOCK)
   LEFT JOIN A a WITH (NOLOCK)
          ON a.a1 = x.x1
   LEFT JOIN B b WITH (NOLOCK)
          ON b.b1 = a.a1 AND LEFT(a.a2, 2) = '--' AND a.a2 NOT IN ('---')
   LEFT JOIN C c WITH (NOLOCK)
          ON c.c1 = a.a1 AND LEFT(a.a2, 2) <> '--' AND a.a2 NOT IN ('---', '---', '--', '--', '--')
   WHERE ISNULL(x.x3, 0) <> 1     
   AND CASE
            WHEN x.x2 IN ('--', '---', '---') THEN '----'
            WHEN x.x2 IN ('---') THEN x.x2
            END = @2
   AND ISNULL(b.b2, c.c2 + c.c3) LIKE  @3

注意:我用虚拟变量替换了大多数值,但它们是一致的。

感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

调用问题,SARGability,当您在where子句或连接中使用函数时,SQL Server无法使用索引。

您可以仅使用ISNULL(x.x3, 0) <> 1替换此x.x3 <> 1,因为空格无论如何都不会匹配。

对于第二个isnull:ISNULL(b.b2, c.c2 + c.c3) LIKE @3,如果您知道在这种情况下c2中的内容,您可以使用union或union all替换为:

select ...
   WHERE ISNULL(x.x3, 0) <> 1     
   AND CASE
            WHEN x.x2 IN ('--', '---', '---') THEN '----'
            WHEN x.x2 IN ('---') THEN x.x2
            END = @2
   AND b.b2 LIKE  @3

union all

select ...
   WHERE ISNULL(x.x3, 0) <> 1     
   AND CASE
            WHEN x.x2 IN ('--', '---', '---') THEN '----'
            WHEN x.x2 IN ('---') THEN x.x2
            END = @2
   AND b.b2 is NULL and c.c2 = @startof3 and c.c3 like @endof3

此外,如果您将LEFT(a.a2, 2) = '--'更改为a.a2 like '--%',则联接可能会有更好的效果,因为这是SARGable。