我遇到了这样的查询:

SELECT (SELECT COUNT(1) FROM Orders o WHERE i.ItemId = o.ItemId) [C]
FROM Items i

我把它改成了以下

;WITH cte_count
AS
(
    SELECT COUNT(1) c, OrderId FROM Orders Group By ItemId
)
SELECT a.c [Count], i.Name
FROM Items i
INNER JOIN cte_count c ON (c.ItemId = i.ItemId)

但两者的执行计划如下所示:

CTE and Inline Execution Plan

同样,还有另一个查询选择 TOP 1 Order By Id.我试着把这个移到 CROSS APPLY 但对于这一个,我也有相同的执行计划。

Cross Apply and Inline Execution Plan

当然,查询中还有其他连接和列。

我的困境是关于使用的效用和优点 CROSS APPLYCTE.是否有任何或它只是异国情调?

有帮助吗?

解决方案

但两者的执行计划如下所示:

计划是不同的。一个是内联接,另一个是外联接。在您的简单测试中,结果可能是相同的,但语义不同。在更复杂的查询中,差异可能会导致更明显的不同执行计划,并带来性能影响。

通常有很多方法可以在SQL中表达相同的要求(或类似的要求,如您的示例中)。您使用的最初是偏好和风格的问题。在某些情况下,使用一个或另一个会产生重要的性能差异,因为声明式SQL通过优化器采用不同的代码路径。在这种特殊情况下,外部联接可能不太适合优化器的探索能力(与内部联接相比,它与外部联接一起使用的工具更少)。

重写查询以定义 使用不同语法的结果可能是一种有效的调优方法,但它需要仔细注意细节,并在修补或升级SQL Server时重新测试。通常没有理由更喜欢在SQL中表达需求的一种方式而不是另一种方式。

此外,正如Andriy在一个 评论 在您的问题的另一个副本上,"在更一般的情况下,您的内联查询每行只会给您一个结果,而连接到CTE(不一定是CTE,可能是正常的子选择)或交叉应用行集可"

其他提示

我的困境是关于使用CROSS APPLY和CTE的效用和优点。是否有任何或它只是异国情调?

对于小数据集,优化器可能不会打扰广泛的分析。但是,如果要查看大型数据集的竞争计划(例如示例中的数百万个订单或项目),那么交叉应用,特别是如果项目被索引,执行速度会更快。

此外,这甚至是适当的检查它像这样,使用执行计划。

当然可以。如果有区别,计划就会显示出来。此外,您肯定会在执行时注意到性能差异。

如果你这样做呢?

SELECT i.Name
       COUNT(o.OrderId) c
FROM   Items i
       JOIN Orders o ON i.ItemID = o.ItemID
GROUP BY i.ItemID

cteapply 它在某些情况下有优势吗我敢肯定,只是可能不是像这样简单的情况

我喜欢用一个 cte 主要是出于美学原因,当我试图创建一个可视化流程,说明如何将较大的结果分解为较小的结果,用于构建最终查询和递归。

apply 当您使用从前一个表中获取param值的表值函数时,这是非常酷的。 cross apply 可以比一个漂亮 full join 声明。

如果你知道你在查询计划中寻找什么,我想这只是一个偏好问题

许可以下: CC-BY-SA归因
不隶属于 dba.stackexchange
scroll top