【问题标题】:CROSS APPLY performance differenceCROSS APPLY 性能差异
【发布时间】:2013-07-08 04:59:05
【问题描述】:

我有一个运行大约 30 秒的 SQL 查询,它返回 1 条记录。 CROSS APPLY 中使用的函数在使用此记录的 BrandId 运行时是即时的。

SELECT 
   b.BrandId,
   b.Name,
   ah.Type,
   c.ContactEmails,
   c.ContactNumbers,
   c.ContactLinks
FROM 
   @IdsToFilterBy ids
JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id
JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId
CROSS APPLY dbo.[fn_GetBrandContactDetails](b.BrandId) AS c

但是,如果我只是更改表,我会从 CROSS APPLY 中获取 BrandId..

SELECT 
   b.BrandId,
   b.Name,
   ah.Type,
   c.ContactEmails,
   c.ContactNumbers,
   c.ContactLinks
FROM 
   @IdsToFilterBy ids
JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id
JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId
CROSS APPLY dbo.[fn_GetBrandContactDetails](ah.RepresentedByBrandId) AS c <-- change here

查询现在只需 2 秒即可运行。当我加入 dbo.Brand b ON cah.RepresentedByBrandId = b.BrandId 时,我希望他们是一样的。

有人能解释一下为什么会有巨大的性能差异吗?

更新

不同之处在于,当我使用 b.BrandId 时,CROSS APPLY 在整个 Brand 表上运行,而当我使用 ah.RepresentedByBrandId 时,则在整个 AccountHandler 表上运行。 AccountHandler 表要小得多。

但是,我希望 CROSS APPLY 仅在 JOIN 的结果上运行,这是一个 1 记录。这是可能的还是我错过了理解 CROSS APPLY?

【问题讨论】:

  • 不同的执行计划没有提示吗?
  • 我不擅长阅读这些内容,但当我使用 b.BrandId 而不仅仅是连接创建的子集时,它似乎运行了整个 Brands 表的交叉应用
  • 可能我是盲人。但是在第二个查询中声明 cah 别名在哪里?
  • @Devart - 敏锐的眼睛,但不是cah在第一个也不是
  • 这与 CROSS APPLY 无关,它(可能)与两个表上的不同索引和数据结构有关。

标签: sql sql-server


【解决方案1】:

我遇到了同样的问题,我使用 OUTER APPLY 而不是 CROSS APPLY 解决了它。

【讨论】:

    【解决方案2】:

    找到了。

    为了强制 CROSS APPLY 在 JOIN 的结果子集上运行,而不是在 JOINS 之前的整个表上运行,我使用了 OPTION (FORCE ORDER)

    SELECT 
       b.BrandId,
       b.Name,
       ah.Type,
       c.ContactEmails,
       c.ContactNumbers,
       c.ContactLinks
    FROM 
       @IdsToFilterBy ids
    JOIN dbo.AccountHandler ah ON ah.AccountHandlerId = ids.Id
    JOIN dbo.Brand b ON ah.RepresentedByBrandId = b.BrandId
    CROSS APPLY dbo.[fn_GetBrandContactDetails](b.BrandId) AS c
    OPTION (FORCE ORDER)
    

    现在立即运行,并查看执行计划,该函数仅针对一个结果而不是整个 db 表被调用。

    【讨论】:

    • FORCE ORDER 并不总是有帮助,我必须使用中间表来存储“主查询”结果,然后将其与函数交叉应用。
    猜你喜欢
    • 2011-10-07
    • 1970-01-01
    • 2020-10-21
    • 2013-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-01
    • 1970-01-01
    相关资源
    最近更新 更多