关于sql server:CROSS APPLY问题 – 过滤多对一关系

CROSS APPLY issue - filtering a many-to-one relationship

我发现了一个关于MS SQL Server如何处理CROSS APPLY的问题。

我正在使用的数据库具有以下模式的定价系统:

Service -> Price Model <- Price Component ('->' indicates a Foreign Key pointing to the table)

有些价格模型有"阶梯式定价",即当金额参数达到不同的阈值时,价格会上涨(1-3个单位为价格A,4-8个单位为价格B等)。

我遇到的问题是[price model id]上的[service]和[price component]之间的EDOCX1[1]正在生成重复的行,因为我实际上并没有使用price component中的price,只是表中的另一个字段对于每个[price component]行都是相同的。

1
2
3
4
SELECT *
  FROM [Service] s
 INNER JOIN [Price Component] pc
    ON s.[Price Model Id] = pc.[Price Model Id]

这个问题的逻辑解决方法是用一个执行此操作的CROSS APPLY替换INNER JOIN

1
2
3
4
5
6
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]表中返回我需要的值,但似乎没有多大帮助:

1
2
3
4
5
6
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解决了与其他连接的问题,但却破坏了交叉应用的目的(据我所知,这基本上是INNER JOINOUTER JOIN之间的区别)。

有没有人对导致CROSS APPLY复杂性疯狂增加的原因有什么想法或见解?

更新

因此,在阅读了更多关于如何解释执行计划的内容之后,我学到了以下几点:

  • 原始查询(使用INNER JOINs)是一系列嵌套循环从你提供的过滤数据开始。漂亮的快餐店只要筛选器位于索引字段上,则响应时间为。

  • 修改后的查询(使用CROSS APPLY是一个较长的哈希序列匹配,并将你给它的每一张桌子连接起来,除了那些筛选,然后最后应用筛选。总是比死亡慢。

  • 使用修改后的查询(使用OUTER APPLY时),与原始,但不排除与WHERE子句。和原版一样快。

所以问题是:为什么一个CROSS APPLY要更改计划以在请求的过滤器之前连接所有表?


为什么不:

1
2
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

如果表中只有一个字段和一个字段,那么您是否考虑过使用group by和max()筛选记录?

1
2
3
4
select a.field1, a.field2, max(b.field3)
from table1 a
join table2 b on a.someid = b.someid
group by a.field1, a.field2


如果JOINCROSS APPLY之间的执行计划不相同,那么查询优化器将使用嵌套循环逻辑运算符,这在某些情况下会对性能产生负面影响。有关嵌套循环的一些基本信息,请参见:http://msdn.microsoft.com/en-us/library/ms191318(v=sql.90).aspx