左联接和 SQL 子查询之间的性能差异

Performance difference between left join and SQL subquery

提问人:Unnamed 提问时间:11/17/2023 最后编辑:Unnamed 更新时间:11/17/2023 访问量:122

问:

这个问题可能很简单,但仍然,SQL Server 查询有什么区别,如下所示:

 SELECT t1.*, t2.Value
 FROM [User] t1
 LEFT JOIN [UserStory] t2 ON t1.Id = t2.Id

 SELECT 
     t1.*, 
     (SELECT Value FROM [UserStory] t2 WHERE t1.Id = t2.Id) 
 FROM User t1

首先,从性能角度来看。

我认为第二个选项不合适,因为正如我所看到的,对于 t1 中的每条记录,服务器应该对 t2 调用单独的查询,我想这里很难优化任何东西。

有人可以评论是否有任何情况,其中带有子查询的第二个选项可能比添加要加入的新表更可取。

新增执行计划:enter image description here

更新:如果我正确阅读了执行计划,两种情况下的性能会相同吗?(如果子查询返回超过 1 条记录,则搁置可能的错误)

sql-server t-sql 左联接 sqlperformance

评论

0赞 Thom A 11/17/2023
您是否咨询过查询计划?
3赞 Thom A 11/17/2023
如果第二个查询中可能有多个相关行,则会出错。Table2
0赞 siggemannen 11/17/2023
它通常取决于价值。如果它是像你的例子一样的简单标量,那就没有意义了。但是,例如,使用 LEFT JOIN 可能更难模拟(select top 1 ...)(select max())
0赞 Unnamed 11/17/2023
Have you consulted the query plans?- 我不是这方面的专家。看起来在这两种情况下都会进行完整的索引扫描。第二种情况下的 2 个额外步骤看起来不需要时间?所以与性能 POV 没有区别?
0赞 Unnamed 11/17/2023
If there could be multiple related rows in Table2 the second query would error- 是的,记录始终是单一的

答:

2赞 David Browne - Microsoft 11/17/2023 #1

任何带有 subquery 的第二个选项可能比添加要联接的新表更可取的任何情况

如果返回多行,则标量子查询将失败。因此,该查询包含查询优化器和试图了解查询工作原理的未来开发人员的其他信息。

因此,如果您知道只会返回一行,但这从表结构中并不明显,那么标量子查询是可取的。

评论

1赞 Martin Smith 11/17/2023
OTOH 添加的断言运算符在子查询确实返回多行时抛出错误,可以限制可用的转换 techcommunity.microsoft.com/t5/sql-server-blog/...
1赞 David Browne - Microsoft 11/17/2023
是的。它是一种查询提示,应始终谨慎使用。
0赞 Unnamed 11/17/2023
我知道如果子查询的结果不止一行就会失败,我的问题主要是关于性能的
0赞 Unnamed 11/17/2023
我添加了执行计划,除非我读错了,否则实际采取的步骤会是一样的吗?
0赞 David Browne - Microsoft 11/17/2023
是的。但是子查询会强制嵌套循环联接。LEFT JOIN 可能使用不同的联接策略或联接顺序。有关详细信息,请查看@MartinSmith发布的链接。