ChatGPT解决这个技术问题 Extra ChatGPT

在 INNER JOIN 条件中使用“或”是一个坏主意吗?

在尝试提高极其缓慢的查询的速度(在两个表上只有大约 50,000 行,如果重要的话,在 SQL Server 2008 上需要几 分钟),我将问题缩小到 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 置于连接条件中通常是个坏主意吗?或者我只是在我的桌子布局上不走运?

向我们展示执行计划而不是您的查询。
似乎是一种奇怪的关系
@Blindy:好主意。事实证明,执行计划显示了 Quassnoi 在下面提到的内容:第一个查询导致嵌套循环,而第二个查询是通过哈希连接完成的。

V
Vaibhav

这种 JOIN 不能针对 HASH JOINMERGE 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 的优化器不够聪明,无法在您编写的查询中看到它(尽管它们在逻辑上是等价的)。


这是有道理的,谢谢。我仍然不确定我的查询是否有什么特殊之处,或者我是否应该完全避免 ON w=x OR y=z 模式的连接?
@ladenedge:这些连接将使用嵌套循环中的表扫描来执行。如果您的表很大,这会很慢。
为了清楚起见,当您说“这些连接”时,您是指 ON w=x OR y=z 形式的所有连接? (谢谢你的耐心!)
@ladenedge:可能有其他条件可以帮助 SQL Server 了解需要串联。比如说,如果两个字段都被索引,那么查询 SELECT * FROM othertable WHERE parentId = 1 OR id = 2 将使用连接,所以理论上没有什么可以阻止在循环中做同样的事情。 SQL Server 是否会实际制定这个计划,取决于很多因素,但我从未在现实生活中看到过它。
另请注意,如果您知道它们是不相交的集合,则 union ALL 可以通过避免合并结果集来显着提高性能。
M
MEO

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

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)

s
sanampakuwal

您可以改用 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

与具有 OR 条件的 JOIN 相比,UNION ALL 将为您提供重复项。
因为那个 UNION 是对的。有关详细信息,请阅读以下链接 union-instead-of-or
是的,但是在您的示例中,您使用 union all 编写了它,这与您链接到的文章所描述的不正确。