我有一个这样的相关子查询(来自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
当我使用连接重写此查询时
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
看看实际的执行计划,它在两个查询中看起来完全一样。为什么?我在想,由于嵌套循环和执行计划看起来不同,相关子查询要慢得多?是因为这些表的数据不多吗?
这两个查询在逻辑上是相同的,并且产生相同的计划。查询优化器的简化阶段处理这个问题。
它们是相同的,因为表上的约束——外键、唯一性、可空性……
一个好的优化器将识别何时可以将相关查询编写为连接并使用相同的计划。许多相关查询可以像连接一样轻松编写。在这种情况下,优化器正在做它的工作。以这种方式优化查询允许使用相关查询没有意义的计划。
我倾向于在语义上有意义时编写相关查询,并在语义上合适时使用连接。现代优化器将生成适当的查询。随着优化器的改进,我然后编写查询以提高可理解性,而不是尝试猜测优化器。(我发现优化器通常比我做的更好。在极少数情况下,我知道优化器无法从查询中确定的内容。)