12

我有一个运行大约 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..

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 记录。这是可能的还是我错过了理解的交叉应用?

4

2 回答 2

23

找到了。

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

于 2013-07-10T13:49:41.460 回答
1

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

于 2015-04-21T11:24:30.687 回答