我发现 MS SQL Server 如何处理CROSS APPLY
.
我正在使用的数据库具有具有以下架构的定价系统:
服务 -> 价格模型 <- 价格组件('->' 表示指向表的外键)
一些价格模型有“阶梯定价”,这意味着当一个数量参数达到各种阈值时,价格会上涨(1-3个单位是价格A,4-8个单位是价格B等)。
我遇到的问题是INNER JOIN
[Price Model ID] 上的 [Service] 和 [Price Component] 之间产生重复的行,因为我实际上并没有使用 Price Component 中的价格,只是表中的另一个字段每个 [Price Component] 行都相同。
SELECT *
FROM [Service] s
INNER JOIN [Price Component] pc
ON s.[Price Model Id] = pc.[Price Model Id]
此问题的合乎逻辑的解决方法是将 替换为执行此操作的INNER JOIN
a CROSS APPLY
:
SELECT *
FROM [Service] s
CROSS APPLY (SELECT TOP 1 *
FROM [Price Component] pc
WHERE s.[Price Model Id] = pc.[Price Model Id]
) AS pc
问题在于,在其他一些看似与此更改无关的连接中,效率完全被破坏了。查看执行计划,过去需要 2.3 个周期的连接现在需要 480 万个周期。
我尝试DISTINCT
在原始查询中添加一个(因为它不使用 [Price Component] 表中的唯一数据,这是一个函数解决方案,除了它将运行时间翻了四倍。我还尝试只返回我需要的值来自 [Price Component] 表,但它似乎没有多大帮助:
SELECT *
FROM [Service] s
CROSS APPLY (SELECT DISTINCT pc.moneyUnitId
FROM [Price Component] pc
WHERE s.[Price Model Id] = pc.[Price Model Id]
) AS pc
奇怪的是,将 the 更改CROSS APPLY
为 an 可以解决其他联接的问题,但却违背了 CROSS APPLY 的目的(据我了解,这基本上是 an和 anOUTER APPLY
之间的区别)。 INNER JOIN
OUTER JOIN
有没有人对可能导致复杂性疯狂增加的原因有任何想法或见解CROSS APPLY
?
更新
因此,在阅读了有关如何解释执行计划的更多信息后,我学到了以下内容:
原始查询(使用
INNER JOIN
s)是一长串嵌套循环,从您提供的任何过滤数据开始。只要过滤器在索引字段上,响应时间就非常快。修改后的查询(使用
CROSS APPLY
)是一个较长的哈希匹配系列,它连接你给它的每个表,除了带有过滤器的表,然后最后应用过滤器。总是比死亡慢。Working Modified 查询(带有
OUTER APPLY
)与原始查询执行相同的操作,但不排除与 WHERE 子句不匹配的结果。和原版一样活泼。
所以问题是:为什么要CROSS APPLY
在请求的过滤器之前更改计划以连接所有表?