我听到了关于这方面的混合信息,希望得到规范或专家的意见。
如果我有多个LEFT OUTER JOIN
s ,每个都依赖于最后一个,嵌套它们是否更好?
对于人为的示例,JOIN
toMyParent
取决于JOIN
to MyChild
:
http ://sqlfiddle.com/#!3/31022/5
SELECT
{columns}
FROM
MyGrandChild AS gc
LEFT OUTER JOIN
MyChild AS c
ON c.[Id] = gc.[ParentId]
LEFT OUTER JOIN
MyParent AS p
ON p.[id] = c.[ParentId]
与http://sqlfiddle.com/#!3/31022/7相比
SELECT
{columns}
FROM
MyGrandChild AS gc
LEFT OUTER JOIN
(
MyChild AS c
LEFT OUTER JOIN
MyParent AS p
ON p.[id] = c.[ParentId]
)
ON c.[Id] = gc.[ParentId]
如上所示,这些在 SS2k8 中产生不同的查询计划
这绝对不是一个规范的答案,但我注意到对于 SQL Fiddle 中显示的嵌套循环查询计划,可以使用
USE PLAN
提示将查询 2 中的计划应用到查询 1,但尝试反向操作失败禁用优化器转换规则
ReorderLOJN
会阻止先前成功的计划提示也成功。对更多数据的试验表明,SQL Server 当然也能够自然地转换
(A LOJ B) LOJ C
为A LOJ (B LOJ C)
,但我没有看到任何相反的证据。第一个查询比第二个查询执行得更好的一个非常人为的情况是
哪个给出计划
对我来说,查询 1 的运行时间为 108 毫秒,而查询 2 的运行时间为 1,163 毫秒。
查询 1
查询 2
因此,可能会暂时假设第一个(“未嵌套”)语法可能是有益的,因为它允许考虑更多潜在的连接顺序,但我还没有进行足够详尽的测试以对此作为一般规则充满信心。
完全有可能提出查询 2 执行得更好的反例。尝试两者并查看执行计划。
没有这种称为“嵌套连接”的连接类型。这是编写 JOIN 的另一种变体,可能是为了便于阅读。您可以将它们视为仅用于理解目的的“子查询”。
如果您更关心代码的可读性,那么我的看法是,他们可以授予什么是个人的选择。
如果您关心查询的性能,并且查询中未使用“Force JOIN ORDER”提示,那么使用“Nested Join”或“All Outer Join”编写查询都没有关系。SQL 服务器根据连接两个表和/或结果的成本得出顺序。SQL Server 一次只在两组数据之间进行 JOIN。
事实上,想象一下,如果 SQL Server 决定执行第二部分“MyChild AS c LEFT OUTER JOIN MyParent AS p ON p.[id] = c.[ParentId]”,那么在第二种方式“嵌套连接”中,这些表会发生拥有将在 NEXT LEFT JOIN 中丢弃的行。在那种情况下,SQL Server 花费了不必要的资源来执行这两个 OUTER JOIN 并将该结果传递给下一个 JOIN。
您也可以在此处查看类似的问题并进行适当的回答。 了解“嵌套连接”语法