是否将约束移入连接比join和where子句更有效?

Jos*_*eld 7 t-sql sql-server sql-server-2008

我一直试图测试这个,但我对我的测试有疑问,因为时间变化太大了.

-- Scenario 1
SELECT * FROM Foo f 
    INNER JOIN Bar b ON f.id = b.id 
    WHERE b.flag = true;

-- Scenario 2 
SELECT * FROM Foo f 
    INNER JOIN Bar b ON b.flag = true AND f.id = b.id;
Run Code Online (Sandbox Code Playgroud)

从逻辑上看,似乎情景2会更有效,但我不确定SQL服务器是否足够聪明以优化这一点.

Aar*_*and 12

不确定为什么你认为方案2会"逻辑上" more efficient.在一个INNER JOIN一切基本上是一个过滤器,以便SQL Server可以折叠的逻辑完全相同的底层平面形状.这是AdventureWorks2012的一个例子(点击放大):

在此输入图像描述

我更喜欢将连接条件与过滤条件分开,因此总是以左侧的格式编写查询.然而@HLGEM提出了一个很好的观点,这些条款在这种情况下是可以互换的,只因为它是一个INNER JOIN.对于a OUTER JOIN,将过滤器放在连接条件中的外部表上非常重要,否则您将无意中最终得到INNER JOIN并大幅更改查询的语义.因此,关于如何折叠计划的建议仅适用于内部联接.

如果你担心性能,我首先要摆脱SELECT *并只拉出你真正需要的列(并确保有覆盖索引).

四个月后,又出现了另一个答案,声称性能通常会有所不同,并且在ON条款中加入过滤条件会更好.虽然我不会怀疑这可能发生这种情况肯定是合理的,但我认为它肯定不是常态,不应该是你用来作为总是将所有过滤标准放在ON条款中的借口.

  • 我知道你知道这一点,但很少有开发人员似乎意识到这一点,我只是认为我会提到它,以便其他人阅读这个问题并没有对他们的问题作出错误的假设. (4认同)
  • 我将补充一点,如果使用左连接,则在将条件放入连接或where子句之间的resust集会有所不同.所以它在那里有所不同,但在性能方面不如结果. (2认同)
  • @HLGEM是的,这是事实.对于交叉连接也是如此.:-)我只对待内心,因为这是问题中特别提到的.干杯. (2认同)