一尘不染

交叉应用效果差异

sql

我有一个SQL查询,大约需要30秒才能运行,返回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时,则在整个AccountHandler表上运行。AccountHandler表要小得多。

但是,我希望CROSS APPLY只能在JOIN的结果上运行,而JOIN的结果是一个1记录。这可能吗?或者我想念CROSS APPLY吗?


阅读 153

收藏
2021-03-17

共1个答案

一尘不染

找到了。

为了强制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表被调用。

2021-03-17