提问人:Unnamed 提问时间:11/17/2023 最后编辑:Unnamed 更新时间:11/17/2023 访问量:122
左联接和 SQL 子查询之间的性能差异
Performance difference between left join and SQL subquery
问:
这个问题可能很简单,但仍然,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 调用单独的查询,我想这里很难优化任何东西。
有人可以评论是否有任何情况,其中带有子查询的第二个选项可能比添加要加入的新表更可取。
更新:如果我正确阅读了执行计划,两种情况下的性能会相同吗?(如果子查询返回超过 1 条记录,则搁置可能的错误)
答:
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发布的链接。
评论
Table2
(select top 1 ...)
(select max())
Have you consulted the query plans?
- 我不是这方面的专家。看起来在这两种情况下都会进行完整的索引扫描。第二种情况下的 2 个额外步骤看起来不需要时间?所以与性能 POV 没有区别?If there could be multiple related rows in Table2 the second query would error
- 是的,记录始终是单一的