sql-server - 将约束移至连接是否比连接和 where 子句更有效?

标签 sql-server sql-server-2008 tsql

我一直在尝试对此进行测试,但我对我的测试有疑问,因为时间差异很大。

-- 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;

从逻辑上讲,方案 2 似乎会更有效,但我不确定 SQL Server 是否足够智能来优化此方案。

最佳答案

不知道为什么你认为场景 2 “逻辑上”是 more efficient 。在INNER JOIN上一切基本上都是一个过滤器,因此 SQL Server 可以将逻辑折叠到完全相同的底层计划形状。以下是来自 AdventureWorks2012 ( click to enlarge ) 的示例:

enter image description here

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

如果您担心性能,我会首先删除 SELECT *并且只提取您实际需要的列(并确保有覆盖索引)。

四个月后,出现了另一个答案,声称性能通常会有差异,并将过滤条件放在ON中条款会更好。虽然我不会否认这种情况确实有可能发生,但我认为这肯定不是常态,也不应该成为您始终将所有过滤条件放在 ON 中的借口。条款。

关于sql-server - 将约束移至连接是否比连接和 where 子句更有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15774878/

相关文章:

SQL - 计算列中出现的次数

sql-server - 添加具有生成名称的 DEFAULT 约束

java - 如何在 Hibernate native 查询中使用常量?

sql - 以......开头的标识符太长。最大长度为 128

sql-server-2008 - Microsoft 的 StreamInsight - 体验和 SQL Server 2008 R2

sql-server-2008 - 如何根据查询结果在 SQL 中写入多个文件?

SQL - 按百分比/合并排名对值进行分组

sql-server - 如何将 "Implode"(反规范化/连接)多个列合并为单个列?

java - Kerberos 身份验证错误 - Sqoop 通过 Hive 从 SQL 导入 HDFS

php - PDOExeption SQLSTATE[HY001] 无法分配足够的内存