代码之家  ›  专栏  ›  技术社区  ›  Josh Anderson

联合能比联合更快吗?还是我的联合就是糟糕的?

  •  4
  • Josh Anderson  · 技术社区  · 14 年前

    我有一个 Notes A表 uniqueidentifier 我用作数据库中各种其他表的FK的列 唯一标识符 其他表上的列不是群集的pk)。这些其他表表示业务对象的某种层次结构。作为一个简单的表示,假设我还有两个表:

    • 引导 (PK LeaDID)
    • 引用 (pk报价,fk leadid)

    在一个 Lead 在应用程序中,我需要显示与销售线索相关的所有注释,包括标记为 Quote 那是属于那条线索的。在我看来,我有两种选择,一种是 UNION ALL 或几个 LEFT JOIN 声明。他们看起来是这样的:

    SELECT N.*  
    FROM Notes N  
    JOIN Leads L ON N.TargetUniqueID = L.UniqueID  
    WHERE L.LeadID = @LeadID
    
    UNION ALL
    
    SELECT N.*  
    FROM Notes N  
    JOIN Quotes Q ON N.TargetUniqueID = Q.UniqueID  
    WHERE Q.LeadID = @LeadID 
    

    或者…

    SELECT N.*  
    FROM Notes N  
    LEFT JOIN Leads L ON N.TargetUniqueID = L.UniqueID  
    LEFT JOIN Quotes Q ON N.TargetUniqueID = Q.UniqueID  
    WHERE L.LeadID = @LeadID OR Q.LeadID = @LeadID
    

    在现实生活中,我总共有五个可以附加注释的表,并且这个数字可以随着应用程序的增长而增长。我已经在上设置了非聚集索引 唯一标识符 我正在使用的列和SQL事件探查器说我不能再做任何改进,但是当我对实际大小的测试数据集进行性能测试时,我得到了以下数字:

    • 联合所有 _0.010秒
    • 左连接 _0.744秒

    我一直听说用 UNION 很糟糕,而且 联合所有 只是稍微好一点,但表现数字似乎无法证明这一点。当然, 联合所有 SQL代码可能更难维护,但在这种性能差异下,它可能是值得的。

    所以是 联合所有 这里好多了,还是我错过了 左连接 代码会减慢速度吗?

    5 回复  |  直到 14 年前
        1
  •  6
  •   Martin Smith    14 年前

    这个 UNION ALL 2个索引查找可能很容易满足版本。 OR 可能导致扫描。执行计划是什么样子的?

    您是否尝试过避免访问 Notes 两次?

    ;WITH J AS
    (
    SELECT UniqueID FROM Leads WHERE LeadID = @LeadID
    UNION ALL
    SELECT UniqueID FROM Quotes WHERE LeadID = @LeadID
    )
    
    SELECT N.*  /*Don't use * though!*/
    FROM Notes N  
    JOIN J ON N.TargetUniqueID = J.UniqueID  
    
        2
  •  2
  •   a1ex07    14 年前

    我可能是错的,但是我认为如果你把你加入的版本改写为

    SELECT N.*  
    FROM Notes N  
    LEFT JOIN Leads L ON N.TargetUniqueID = L.UniqueID AND L.LeadID = @LeadID  
    LEFT JOIN Quotes Q ON N.TargetUniqueID = Q.UniqueID  AND Q.LeadID = @LeadID
    WHERE Q.LeadID IS NOT NULL OR L.LeadID IS NOT NULL
    
        3
  •  1
  •   Frank    14 年前

    根据我的经验,SQL Server对于包含 OR . 我也用 UNION 在这种情况下,我得到了和你相似的结果(可能是半秒而不是20秒)。

    谁说工会不好?尤其是当你使用 UNION ALL 不应出现性能问题,因为 联合 必须通过结果才能保留唯一的记录(实际上做了一些类似于distinct或 group by )

        4
  •  1
  •   HLGEM    14 年前

    第二个查询甚至不会给出正确的结果,因为它会将左联接转换为内部联接,请参阅此处了解有关语法错误的原因的解释:

    http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN

        5
  •  0
  •   Dean J    14 年前

    联合比较慢,但联合应该很快,对吧?