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

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 时,CROSS APPLY 是在整个 AccountHandler 表上运行的。 AccountHandler 表要小得多。

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

最佳答案

找到了。

为了强制 CROSS APPLY 在 JOIN 的结果子集上运行而不是在 JOIN 之前的整个表上运行,我使用了 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)

现在立即运行并查看执行计划,该函数只为一个结果而不是整个数据库表调用。

关于sql - CROSS APPLY 性能差异,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17567674/

10-13 04:44