sql-server - CROSS APPLY 问题 - 过滤多对一关系

标签 sql-server performance cross-apply

我发现 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 JOINCROSS 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 APPLYOUTER APPLY修复了其他连接的问题,但违背了 CROSS APPLY 的目的(据我所知,这基本上是 INNER JOINOUTER 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/

    相关文章:

    sql-server - 长度与精度

    c# - 提高应用程序性能

    java - 未使用的基元数组 : what do javac and the JIT compiler do with it?

    sql - OPENJSON 与 NULL 值交叉应用 (SQL)

    sql-server - 为什么要使用交叉Apply来获取XML中的值?

    sql-server - 创建笛卡尔积时,CROSS APPLY 和 OUTER APPLY 有什么区别吗?

    sql-server - SQL Server 2008 中 Oracle 的 LAST_DAY() 函数的等价物是什么?

    java - 性能和可伸缩性的架构问题

    c# - Entity Framework : Table with Composite Key issue : Violation of PRIMARY KEY constraint. 无法在对象中插入重复键

    c# - 列表上的 IndexOf 太慢。更快的解决方案?