SQL Server:全外连接的顺序是否重要?

6
我查询中有4个全外连接,速度非常慢,所以FULL OUTER JOIN的顺序会对性能/结果产生影响吗? FULL OUTER JOIN = ⋈ 那么,
我有一个情况:A ⋈ B ⋈ C ⋈ D
所有连接都在所有A、B、C、D中包含的共同键k上发生。
然后:
  • 更改⋈连接的顺序是否会影响性能?
  • 更改⋈连接的顺序会改变结果吗?
我认为这不应该影响结果,但是它是否会影响性能我不确定!
更新:
如果结果集与顺序无关,SQL Server是否会自动重新排列连接以获得更好的性能?

1
结果应该是相同的。检查性能非常容易。比较从少到多点击次数或反向顺序订购表格所需的时间。 - Klas Lindbäck
为何不试试呢?看看不同组合的执行计划和SQL Profiler跟踪。 - EBarr
当您说“不同的顺序”时,您是指例如 (a FULL JOIN b) FULL JOIN ca FULL JOIN (b FULL JOIN c) - ypercubeᵀᴹ
是的和不是的。如果你先放置最严格的限制条件,那么查询的其余部分将有较少的连接。但是,如果您无法至少一般性地保证这一点,那么以这种方式进行调整就没有多大用处。如果您发布查询计划(只需在查询之前加上“Explain”并运行它,然后将结果添加到您的问题中),我们可能能够更好地帮助您。最好看看为什么需要这么多的全外连接。 - Tony Hopkinson
我有第一张表中的10万行数据。检查它们需要数小时时间。我想知道是否有自动重新排列以提高性能的方法? - Yugal Jindle
3个回答

8
不,重新排列JOIN顺序不应影响性能。MSSQL(以及其他DBMS)都有查询优化器,其工作是找到任何给定查询的最有效查询计划。一般来说,这些做得很好-因此您不太可能轻易击败优化器。
话虽如此,它们偶尔会出错。这就是阅读执行计划发挥作用的地方。您可以添加JOIN提示来告诉MSSQL如何连接表格(在这一点上,顺序确实很重要)。通常,您会按从小到大的顺序排序表格(尽管使用FULL JOIN,这并不太重要),并遵循连接类型的经验法则

由于您正在执行FULL JOINS,因此基本上是从磁盘读取了4个表的全部内容。这很可能非常昂贵。您可能需要重新审视问题,并查看是否可以以不同的方式完成。


1
+1:针对楼主的问题,需要注意的是SQL并不是以本地和原始方式执行的。它实际上只是一种算法表达式,用于告诉优化器您问题的功能描述。然后,优化器会有效地编译它并执行一个计划,该计划几乎完全独立于SQL。 - MatBailie

4
  • 改变⋈的顺序会改变结果吗?

不,FULL JOIN的顺序不重要,结果将是相同的。然而请注意,您不能使用以下语句(根据连接的顺序,下面的查询可能会给出不同的结果):

SELECT 
    COALESCE(a.id, b.id, c.id, d.id) AS id,  --- Key columns used in FULL JOIN
    a.*, b.*, c.*, d.*                       --- other columns                 
FROM a 
  FULL JOIN b
      ON b.id = a.id
  FULL JOIN c
      ON c.id = a.id
  FULL JOIN d
      ON d.id = a.id ;

你需要使用以下类似的语句(无论连接顺序如何,结果相同):
SELECT 
    COALESCE(a.id, b.id, c.id, d.id) AS id,   
    a.*, b.*, c.*, d.*                                   
FROM a 
  FULL JOIN b
      ON b.id = a.id
  FULL JOIN c
      ON c.id = COALESCE(a.id, b.id) 
  FULL JOIN d
      ON d.id = COALESCE(a.id, b.id, c.id) ;

  • 调整⋈连接的顺序对性能有影响吗?

考虑到第二个和第三个连接必须在列的COALESCE()而不是列本身上完成,我认为只有使用足够大的表进行测试才能确定索引是否可以有效使用。


我没有任何合并情况。另外,请查看问题中的更新! - Yugal Jindle
@Yugal:你的意思是什么?你能发两个版本的查询吗,这样我们就能理解你的意思了吗?如果不使用COALESCE(),你是如何连接的? - ypercubeᵀᴹ
@Yugal:正如我回答的第一部分所说,根据连接的顺序,您可能会得到不同的结果。 - ypercubeᵀᴹ
如果您不使用COALESCE函数,则会根据顺序混合使用全外连接和内连接。 您需要使用COALESCE函数来实现您想要的结果。 - Gordon Linoff

0

改变全外连接的顺序不应该影响性能或结果。唯一会受到影响的是使用SELECT *时产生的列的默认顺序。如果尝试对大表进行多次连接,可能会出现性能问题。如果没有where子句来限制表格,您可能需要处理数十万个结果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接