LEFT JOIN明显快于INNER JOIN

Gre*_*reg 22 sql performance join sql-server-2005

我有一个表(MainTable)有超过600,000条记录.它通过JoinTable父/子类型关系中的第二个表()连接到自身:

SELECT   Child.ID, Parent.ID
FROM     MainTable
AS       Child
JOIN     JoinTable
      ON Child.ID = JoinTable.ID
JOIN     MainTable
AS       Parent
      ON Parent.ID = JoinTable.ParentID
     AND Parent.SomeOtherData = Child.SomeOtherData
Run Code Online (Sandbox Code Playgroud)

我知道每个子记录都有父记录,JoinTable中的数据是精确的.

当我运行此查询时,运行需要几分钟.但是,如果我使用左连接加入Parent,则运行时间<1秒:

SELECT   Child.ID, Parent.ID
FROM     MainTable
AS       Child
JOIN     JoinTable
      ON Child.ID = JoinTable.ID
LEFT JOIN MainTable
AS       Parent
      ON Parent.ID = JoinTable.ParentID
     AND Parent.SomeOtherData = Child.SomeOtherData
WHERE    ...[some info to make sure we don't select parent records in the child dataset]...
Run Code Online (Sandbox Code Playgroud)

我理解INNER JOINa和a 之间结果的差异LEFT JOIN.在这种情况下,它返回的结果完全相同,因为每个孩子都有父母.如果我让两个查询都运行,我可以比较数据集,它们完全相同.

为什么LEFT JOIN运行速度比运行速度快得多INNER JOIN


更新检查查询计划,使用内部联接时,它以父数据集开头.在进行左连接时,它以子数据集开始.

它使用的索引都是一样的.

我可以强迫它始终与孩子一起开始吗?使用左连接有效,只是感觉不对.


之前有人问过类似的问题,但似乎没有人回答我的问题.

例如,INNER JOIN中的选定答案与SQL Server中的LEFT JOIN性能表示左连接总是慢于内连接.这个论点是有道理的,但这不是我所看到的.

Gre*_*reg 13

左连接似乎更快,因为SQL被迫首先执行较小的选择,然后连接到这个较小的记录集.出于某种原因,优化者不希望自然地这样做.

强制联接按正确顺序发生的3种方法:

  1. 选择第一个数据子集到临时表(或表变量)然后加入它
  2. 使用左连接(并记住这可能返回不同的数据,因为它是左连接而不是内连接)
  3. 使用FORCE ORDER关键字.请注意,如果表大小或模式更改,则查询计划可能不正确(请参阅https://dba.stackexchange.com/questions/45388/forcing-join-order)