パラメータ化されたテーブル値関数のCROSS APPLY
に問題があります。簡略化した疑似コードの例を次に示します。
SELECT *
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) AS lor
CROSS APPLY dbo.HeavyTableValuedFunction(lor.ID) AS htvf
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
WHERE ...
LOT_OF_ROWS_TABLE
の内部選択が多くの行を返しています。LOT_OF_ROWS_TABLE
とANOTHER_TABLE
を結合すると、1行または数行のみが返されます。私の問題:
関数は、LOT_OF_ROWS_TABLE
を結合するだけでデータが制限されるという事実に関係なく、ANOTHER_TABLE
から返されるすべての行に対して呼び出されます。
選択は表示された形式である必要があります-生成されますが、実際にははるかに困難です。
それを書き直そうとすると、非常に高速になる可能性がありますが、次のように書き換えることはできません。
SELECT *
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) AS lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
CROSS APPLY dbo.HeavyTableValuedFunction(at.ID) AS htvf
WHERE ...
知りたい:
最終的に制限された行に対してのみselectが関数を呼び出すように強制する設定やヒントなどはありますか?
ありがとうございました。
編集:
テーブル値関数は非常に複雑です: http://Pastebin.com/w6azRvxR 。私たちが話している選択は「ユーザー設定」であり、生成されます: http://Pastebin.com/bFbanY2n 。
このクエリを2つの部分に分割できます。テーブル変数または一時テーブルを使用します。
SELECT lor.*,at.* into #tempresult
FROM (
SELECT lor.*
FROM LOT_OF_ROWS_TABLE lor
WHERE ...
) lor
INNER JOIN ANOTHER_TABLE AS at ON lor.ID = at.ID
WHERE ...
時間のかかる部分であるテーブル値関数を実行する
SELECT * FROM #tempresult
CROSS APPLY dbo.HeavyTableValuedFunction(#tempresult.ID) AS htvf
これはあなたが探しているものだと思います。
プラン強制シナリオ:書き換えられたクエリから取得したプランを強制するプランガイドを作成する
基本的には、正しい結合順序を使用して生成されたプランを取得するためのクエリの書き直しについて説明しています。次に、その計画を保存し、保存した計画を使用するように既存のクエリ(変更されない)を強制します。
私が入れたBOLリンクは、結合を別の順序で入れ、FORCE ORDER
ヒント。次に、sp_create_plan_guild
再作成されたクエリからプランを取得して、元のクエリで使用します。
YESとNO ...結果を比較するために、サンプルデータINと結果OUTなしで達成しようとしていることを解釈することは困難です。
知りたい:
最終的に制限された行に対してのみselectが関数を呼び出すように強制する設定やヒントなどはありますか?
だから私は直接あなたの質問に答えます(3年後!!)、直接の声明で:
CTE、およびCROSS APPLYとINNER JOINの違い、およびケースでCROSS APPLYを使用する必要がある理由を理解する必要があります。関数のコードを「取り得」、CTEを使用して単一のSQLステートメントに適用できます。
つまり:
基本的に、このようなもの...
WITH t2o AS
(
SELECT t2.*, ROW_NUMBER() OVER (PARTITION BY t1_id ORDER BY rank) AS rn
FROM t2
)
SELECT t1.*, t2o.*
FROM t1
INNER JOIN
t2o
ON t2o.t1_id = t1.id
AND t2o.rn <= 3
クエリを適用してONCEが必要な日付を推定し、CTEを使用してから、CROSS APPLYを使用して2番目のSQLを適用します。
あなたは選択肢がありません。 ONE SQLでやろうとしていることはできません。