12

実行に約 30 秒かかり、1 つのレコードを返す SQL クエリがあります。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 が 1 つのレコードである JOIN の結果だけで実行されることを期待していました。これは可能ですか、それとも CROSS APPLY を理解できませんでしたか?

4

2 に答える 2

23

それを見つけた。

CROSS APPLY を、結合前のテーブル全体ではなく、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)

これはすぐに実行され、実行計画を見ると、関数は db テーブル全体ではなく、1 つの結果に対してのみ呼び出されています。

于 2013-07-10T13:49:41.460 に答える
1

同じ問題があり、CROSS APPLY の代わりに OUTER APPLY を使用して解決しました。

于 2015-04-21T11:24:30.687 に答える