UNION ALL可以比JOIN快,还是我的JOIN只是吮吸?

时间:2010-07-30 18:43:24

标签: tsql sql-server-2008

我有一个Notes表,其中uniqueidentifier列用作数据库中各种其他表的FK(不用担心,uniqueidentifier列上的Lead列其他表不是群集PK)。这些其他表表示业务对象层次结构的某些内容。作为一个简单的表示,假设我还有另外两个表:

  • 潜在客户(PK LeadID)
  • 报价(PK QuoteID,FK LeadID)

在应用程序中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

或者...

uniqueidentifier

在现实生活中,我总共有五个表可以附加注释,并且随着应用程序的增长,这个数字会增长。我已经在我正在使用的UNION ALL列上设置了非聚集索引,而SQL Profiler说我无法进行任何进一步的改进,但是当我对实际大小的测试数据集进行性能测试时,我得到以下数字:

  • LEFT JOIN - 0.010秒
  • UNION - 0.744秒

我一直听说使用UNION ALL是不好的,UNION ALL只是略微好一点,但性能数字似乎并不能证明这一点。当然,UNION ALL SQL代码可能更难以维护,但在这种性能差异下,它可能是值得的。

LEFT JOIN在这里真的更好吗?或者我在{{1}}代码上遗漏了哪些内容会减慢速度?

5 个答案:

答案 0 :(得分:6)

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  

答案 1 :(得分:2)

我可能错了,但我认为如果你将JOIN版本改写为

,你会获得更好的表现
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

答案 2 :(得分:1)

根据我的经验,对于包含OR的连接条件,SQL Server非常糟糕。在这种情况下我也使用UNION s,我得到的结果与你类似(可能是半秒而不是20秒)。

谁说UNIONS不好?特别是如果您使用UNION ALL,则不应该有性能损失,因为UNION必须通过结果才能保留唯一记录(实际上执行类似distinct或group by的操作)。

答案 3 :(得分:1)

你的第二个查询甚至不会给出正确的结果,因为它会将左连接转换为内连接,请参阅此处以解释为什么你的语法不好:

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

答案 4 :(得分:0)

UNION速度较慢,但​​UNION ALL应该很快,对吧?