我发现 MS SQL Server 如何处理 CROSS APPLY
的问题.
我正在使用的数据库有一个具有以下架构的定价系统:
Service -> Price Model <- Price Component ('->' indicates a Foreign Key pointing to the table)
一些价格模型有“阶梯定价”,这意味着当一个金额参数达到各种阈值时,价格会上涨(1-3个单位是价格A,4-8个单位是价格B等)。
我遇到的问题是
INNER JOIN
[价格模型 ID] 上的 [服务] 和 [价格组件] 之间产生重复的行,因为我实际上并没有使用价格组件中的价格,只是表中的另一个字段对于每个 [价格组件] 行。SELECT *
FROM [Service] s
INNER JOIN [Price Component] pc
ON s.[Price Model Id] = pc.[Price Model Id]
此问题的逻辑修复是替换
INNER JOIN
与 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
奇怪的是,改变了
CROSS APPLY
到 OUTER APPLY
修复了其他连接的问题,但违背了 CROSS APPLY 的目的(据我所知,这基本上是 INNER JOIN
和 OUTER JOIN
之间的区别)。是否有人对可能导致
CROSS APPLY
的复杂性疯狂增加的原因有任何想法或见解? ?更新
因此,在阅读了有关如何解释执行计划的更多信息后,我了解到以下内容:
INNER JOIN
s)是一长串嵌套循环从您提供的任何过滤数据开始。很活泼
只要过滤器在索引字段上的响应时间。
CROSS APPLY
)是一个更长的哈希系列匹配,并加入你给它的每一张 table ,除了那些
过滤器,然后最后应用过滤器。永远比死还慢。
OUTER APPLY
),与原始的,但不排除与结果不匹配的结果
WHERE 子句。和原版一样活泼。
所以问题是:为什么
CROSS APPLY
在请求的过滤器之前更改计划以连接所有表?
最佳答案
为什么不:
select t1.colA, t3.colX from table1 t1
inner join (select distinct t2.t1FK, t2.colX from table2 t2) t3 on t1.ID = t3.t1FK
关于sql-server - CROSS APPLY 问题 - 过滤多对一关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7663123/