4

我发现 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 JOINa 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 JOINOUTER JOIN

有没有人对可能导致复杂性疯狂增加的原因有任何想法或见解CROSS APPLY

更新

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

  • 原始查询(使用INNER JOINs)是一长串嵌套循环,从您提供的任何过滤数据开始。只要过滤器在索引字段上,响应时间就非常快。

  • 修改后的查询(使用CROSS APPLY)是一个较长的哈希匹配系列,它连接你给它的每个表,除了带有过滤器的表,然后最后应用过滤器。总是比死亡慢。

  • Working Modified 查询(带有OUTER APPLY)与原始查询执行相同的操作,但不排除与 WHERE 子句不匹配的结果。和原版一样活泼。

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

4

3 回答 3

1

为什么不:

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
于 2012-11-14T17:43:00.977 回答
0

If you are only using one field from the table with the one-many have you considered using group by and max() to filter the records?

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
于 2011-10-05T19:54:47.783 回答
0

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

于 2011-10-05T15:53:15.897 回答