我有一个大约需要 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/