相关子查询和连接:仍然是相同的执行计划?

jra*_*ara 7 query execution-plan sql-server-2008-r2

我有一个这样的相关子查询(来自BOL):

SELECT DISTINCT c.LastName, c.FirstName, e.BusinessEntityID 
FROM Person.Person AS c JOIN HumanResources.Employee AS e
ON e.BusinessEntityID = c.BusinessEntityID 
WHERE 5000.00 IN
    (SELECT Bonus
    FROM Sales.SalesPerson sp
    WHERE e.BusinessEntityID = sp.BusinessEntityID) ;
GO
Run Code Online (Sandbox Code Playgroud)

当我使用连接重写此查询时

select c.LastName, c.FirstName, e.BusinessEntityID, d.Bonus
from Person.Person as c 
    inner join HumanResources.Employee as e on e.BusinessEntityID = c.BusinessEntityID
    inner join Sales.SalesPerson as d on d.BusinessEntityID = c.BusinessEntityID
where Bonus = 5000.00
Run Code Online (Sandbox Code Playgroud)

看看实际的执行计划,它在两个查询中看起来完全一样。为什么?我在想,由于嵌套循环和执行计划看起来不同,相关子查询要慢得多?是不是因为这些表的数据不多?

Rob*_*ley 11

这两个查询在逻辑上是相同的,并且产生相同的计划。查询优化器的简化阶段处理这个问题。

由于表上的约束,它们是相同的——外键、唯一性、可空性......


Bil*_*hor 5

一个好的优化器会识别何时可以将相关查询编写为连接并使用相同的计划。许多相关查询可以像连接一样轻松编写。在这种情况下,优化器正在做它的工作。以这种方式优化查询允许使用相关查询没有意义的计划。

我倾向于在语义上有意义时编写相关查询,并在语义上合适时使用连接。现代优化器将生成适当的查询。随着优化器的改进,我会编写查询以提高可理解性,而不是尝试再次猜测优化器。(我发现优化器通常比我做的更好。在极少数情况下,我知道优化器无法从查询中确定的内容。)