2013-04-26 10 views
7

パラメータ化されたテーブル値関数を持つ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_TABLEANOTHER_TABLEは、1行または数行しか返しません。
  • テーブル値関数は非常に時間がかかり、多くの 行を呼び出すと、選択時間が非常に長くなります。

私の問題は:すべての行が関係なく、ただANOTHER_TABLEに参加するとき、データが制限されるという事実のLOT_OF_ROWS_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関数が関数を呼び出すようにしますか?

ありがとうございます。

EDIT:

テーブル値関数は非常に複雑です:http://pastebin.com/w6azRvxR。 私たちが話しているセレクトは「ユーザー設定」で、生成されたものはhttp://pastebin.com/bFbanY2nです。

+0

明白なことを明記してください:クエリテキスト内の結合の順序を変更できるのはあなただけです。その後、FORCE_ORDERクエリヒントを使用できました。コードはどのように生成されますか?その目的のために行動を変える方法はありませんか? –

+0

'dbo.HeavyTableValuedFunction(..)'の複数行のテーブル値関数をインラインテーブル値関数に変更します。 – RBarryYoung

+0

@RBarryYoung:単純すぎてインライン関数に書き直すには複雑すぎる –

答えて

2

あなたは2つの部分には、このクエリを分割することができますが、今右

SELECT * FROM #tempresult 
CROSS APPLY dbo.HeavyTableValuedFunction(#tempresult.ID) AS htvf 
+0

ありがとうございますが、私はこれを行うことができません。なぜなら、 'lor'テーブルとクロス・アプライは一緒でなければならないからです。複雑な生成クエリ内のユニットを表します(実際には、another_tableは、最終的な制約を表すレコードを含む一時テーブル変数です)。 –

1

テーブル値関数である時間の一部を消費するが、私はこれは何であると信じていないテーブル変数や一時テーブル

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 ... 

のいずれかを使用しますあなたは探している。

Plan Forcing Scenario: Create a Plan Guide to Force a Plan Obtained from a Rewritten Query

基本的には加入の正しい順序を使用して生成されたプランを取得するには、再書き込みクエリを記述しています。その後、そのプランを保存せずに保存したプランを使用するように既存のクエリ(変更されない)を強制します。

私が入れたBOLリンクでも、クエリを再書き込みして結合を別の順序で入れ、FORCE ORDERのヒントを使用して具体的な例を示します。その後、sp_create_plan_guildを使用して、書き直したクエリからプランを取り出し、元のクエリで使用します。

+0

残念ながら、選択は「ユーザ設定」され、生成され、より多くの他のテーブルに参加することができます - 私は計画を予測できません。 –

0

YESとNO ...結果を比較するために、サンプルデータINと結果OUTなしで達成しようとしているものを補間するのは難しいです。

私が知りたいのです:

は、任意の設定やヒントや力だけでようやく制限行に対して 機能を呼び出すために選択するものがありますか?

だから私は(!! 3年後)の上に、あなたの疑問にお答えします、直接、直接の文で:

あなたはCTEとCROSSの違いについて学ぶ必要があるINNERに比べ を適用あなたのケースでCROSS APPLYを使用する理由は、 が必要です。関数内でコードを受け取り、CTEを使用して を単一のSQL文に適用することができます。

すなわち:

読むthisthis

基本的に、このような何か...

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を適用します。

あなたは選択の余地がありません。あなたは1つのSQLでやろうとしていることをすることはできません。

関連する問題