【问题标题】:SQL Stored Proc; using ISNULL(db1.value, db2.value) performance issueSQL 存储过程;使用 ISNULL(db1.value, db2.value) 性能问题
【发布时间】:2015-08-13 18:49:07
【问题描述】:

尝试调试存储过程以找出它永远不会结束的原因(等待 > 2 分钟)。 proc 有 3 个左连接,然后在底部是一个 ISNULL,它正在检查一个 db 是否有一个值为空的值,然后用来自第二个 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

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

感谢您的帮助。

【问题讨论】:

  • 虽然ISNULL(b.b2, c.c2 + c.c3) LIKE @3这行性能还是不错的?或性能在ISNULL(x.x3, 0) &lt;&gt; 1 行受到影响?主题和问题暗示了 where 子句中的最后一个,但不确定......逻辑上如果 b.b2 为空...... c.c2+c.c3 也可能为空。添加空值会导致空值,但然后比较像@3 这样的空值会出现问题。如果是字符串,则可能是 ISNULL(b.b2, coalesce(c.c2,'') + coalesce(c.c3,'')),如果 c c.c2 和 c.c3 是数字,则可能是 ISNULL(b.b2, coalesce(c.c2,0) + coalesce(c.c3,0))
  • 抱歉含糊不清; b.b2, c.c2, c.c3 是字符串。是的,问题出现在 ISNULL(b.b2....) 处,b2 将为空,或者 c2 和 c3 将为空,但 b2 和 c2/c3 都不会。如果有帮助的话,@3 也是一个 VARCHAR(15) 。也感谢您的回答。
  • 你能举个例子说明@3、c.c2 和 c.c3 什么时候会“实现”吗?我很好奇类似的东西是否有 % 或 SQL 是什么想在执行之前。此外,来自 SQL Server 的执行计划的屏幕截图可能有助于找出瓶颈所在。

标签: sql sql-server performance stored-procedures


【解决方案1】:

问题是调用,SARGability,当你有where子句或join中使用的函数时,SQL Server不能使用索引。

您可以将这个 ISNULL(x.x3, 0) &lt;&gt; 1 替换为 x.x3 &lt;&gt; 1,因为无论如何 null 都不会匹配。

对于第二个 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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-03
    • 2013-01-05
    • 1970-01-01
    • 2011-08-12
    • 1970-01-01
    • 2015-06-09
    相关资源
    最近更新 更多