TLDR;如果您查看 2 个执行计划,是否可以轻松回答哪个更好?我故意没有创建索引,所以更容易看到发生了什么。
继续我之前的问题,我们发现不同连接样式(即嵌套与传统)之间的查询性能差异,我意识到嵌套语法也会修改查询的行为。考虑以下 2 个查询。
SELECT a.*, m.*, n.*
FROM dbo.Autos a
LEFT JOIN dbo.Models m
JOIN dbo.Manufacturers n -- <-- Nested INNER JOIN
ON n.ManufacturerID = m.ManufacturerID
ON m.ModelID = a.ModelID
Run Code Online (Sandbox Code Playgroud)
这并不一定使制造商加入,以包括与ModelID自动行是不是在型号表。
使用传统语法,我们必须将 Manufactures 的连接更改为外部连接,就像这样……但这会改变查询计划。
SELECT a.*, m.*, n.*
FROM dbo.Autos a
LEFT JOIN dbo.Models m
ON m.ModelID = a.ModelID
LEFT JOIN dbo.Manufacturers n -- <-- Now LEFT OUTER JOIN
ON n.ManufacturerID = m.ManufacturerID
Run Code Online (Sandbox Code Playgroud)
我养成了将连接条件与其他附加条件分开的习惯。不过我理解逻辑执行顺序是:
where
如果我在子句中而不是子句中添加附加条件,是否会对性能产生不利影响join
?或者这通常是在查询优化阶段得到简化和同等处理的部分?
以下是两个简单的示例查询,它们都返回相同的计划:
USE StackOverflow2010;
-- additional filters in where clause
SELECT TOP 500 p.id
FROM dbo.Posts p
INNER JOIN dbo.Votes v ON p.id = v.PostId
WHERE
v.VoteTypeId = 2
ORDER BY p.id
;
-- all criteria in on clause
SELECT TOP 500 p.id
FROM dbo.Posts p
INNER JOIN dbo.Votes v ON p.id = v.PostId AND v.VoteTypeId = 2
ORDER BY p.id
;
Run Code Online (Sandbox Code Playgroud)
我想补充一点,如果我编写较长的分析语句,通常跨越 100 行以上(格式化),我会尝试尽快减少结果集,通常使用派生表,并在到达连接之前添加一个额外的位置。