在INNER JOIN条件下使用“ OR”是个坏主意吗?


94

为了提高超慢查询的速度(如果有关系,请在SQL Server 2008上,在两个表中各只有几分钟,每行只有约50,000行,要花几分钟),将问题缩小到OR内部联接中,例如:

SELECT mt.ID, mt.ParentID, ot.MasterID
  FROM dbo.MainTable AS mt
  INNER JOIN dbo.OtherTable AS ot ON ot.ParentID = mt.ID
                                  OR ot.ID = mt.ParentID

我将其更改为(希望是)一对等效的左联接,如下所示:

SELECT mt.ID, mt.ParentID,
   CASE WHEN ot1.MasterID IS NOT NULL THEN
      ot1.MasterID ELSE
      ot2.MasterID END AS MasterID
  FROM dbo.MainTable AS mt
  LEFT JOIN dbo.OtherTable AS ot1 ON ot1.ParentID = mt.ID
  LEFT JOIN dbo.OtherTable AS ot2 ON ot2.ID = mt.ParentID
  WHERE ot1.MasterID IS NOT NULL OR ot2.MasterID IS NOT NULL

..并且查询现在运行大约一秒钟!

将联接置于OR联接条件通常不是一个好主意吗?还是我只是不幸地布置了桌子?


6
向我们显示执行计划,而不是您的查询。
布林迪

似乎是一种奇怪的关系
森·冈萨雷斯

@Blindy:好主意。事实证明,执行计划仅显示了Quassnoi在下面提到的内容:第一个查询导致嵌套循环,而第二个查询则通过哈希联接完成。
ladenedge,2011年

Answers:


114

这种JOIN对a HASH JOIN或a 不乐观MERGE JOIN

它可以表示为两个结果集的串联:

SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.parentId = m.id
UNION
SELECT  *
FROM    maintable m
JOIN    othertable o
ON      o.id = m.parentId

,它们中的每个都是等值联接,但是,SQL Server优化器的智能程度不足以在您编写的查询中看到它(尽管它们在逻辑上是等效的)。


3
这很有意义,谢谢。我仍然不确定我的查询是否有某些特殊之处,还是应该完全避免ON w=x OR y=z模式的联接?
ladenedge,2011年

@ladenedge:这些联接将使用嵌套循环中的表扫描来执行。如果您的桌子很大,这很慢。
Quassnoi

只是为了清楚起见,当您说“这些联接”时,是指该形式的所有联接ON w=x OR y=z?(感谢您的耐心!)
ladenedge

3
@ladenedge:可能还有其他条件可以帮助SQL Server理解需要进行级联。说,SELECT * FROM othertable WHERE parentId = 1 OR id = 2如果两个字段都被索引,则查询将使用连接,因此从理论上讲,没有什么可以阻止在循环中执行相同的操作。是否SQL Server实际制定该计划取决于很多因素,但是我从未见过它是在现实生活中制定的。
Quassnoi

4

我使用以下代码从对我有用的条件中获得不同的结果。


Select A.column, B.column
FROM TABLE1 A
INNER JOIN
TABLE2 B
ON A.Id = (case when (your condition) then b.Id else (something) END)

-2

您可以改用UNION ALL。

SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.MainTable AS mt Union ALL SELECT mt.ID, mt.ParentID, ot.MasterID FROM dbo.OtherTable AS ot


UNION ALLJOINOR条件相比,将为您提供重复项。
CodeMonkey

为此,UNION是正确的。有关更多详细信息,请阅读下面的链接,而不是联合
Mitul Panchal,

1
是的,但是在您的示例中,您所写的内容union all并不正确,因为所链接的文章也对此进行了描述。
CodeMonkey
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.