202

OPTION (RECOMPILE)クエリに追加すると 0.5 秒で実行され、それを省略するとクエリに 5 分以上かかるという奇妙な状況に遭遇しました。

これは、Query Analyzer または C# プログラムからSqlCommand.ExecuteReader(). 電話する(または電話しない)DBCC FREEPROCCACHEDBCC dropcleanbuffers、違いはありません。クエリの結果は、クエリがある場合は常に瞬時に返され、クエリがOPTION (RECOMPILE)ない場合は 5 分以上返されます。[このテストのために] クエリは常に同じパラメーターで呼び出されます。

SQL Server 2008 を使用しています。

私は SQL を書くことにかなり慣れていますが、これまでOPTIONクエリでコマンドを使用したことがなく、このフォーラムの投稿をスキャンするまでプラン キャッシュの概念全体に慣れていませんでした。投稿からの私の理解は、それOPTION (RECOMPILE)は高価な操作であるということです。どうやら、クエリの新しいルックアップ戦略を作成します。では、なぜ を省略した後続のクエリOPTION (RECOMPILE)が非常に遅いのでしょうか? 後続のクエリは、再コンパイルのヒントを含む前回の呼び出しで計算されたルックアップ戦略を利用するべきではありませんか?

呼び出しごとに再コンパイルのヒントが必要なクエリがあるのは非常に珍しいことですか?

初心者レベルの質問で申し訳ありませんが、これについては頭も尻もわかりません。

更新: クエリを投稿するように求められました...

select acctNo,min(date) earliestDate 
from( 
    select acctNo,tradeDate as date 
    from datafeed_trans 
    where feedid=@feedID and feedDate=@feedDate 

    union 

    select acctNo,feedDate as date 
    from datafeed_money 
    where feedid=@feedID and feedDate=@feedDate 

    union 

    select acctNo,feedDate as date 
    from datafeed_jnl 
    where feedid=@feedID and feedDate=@feedDate 
)t1 
group by t1.acctNo
OPTION(RECOMPILE)

Query Analyzer からテストを実行するときは、次の行を先頭に追加します。

declare @feedID int
select @feedID=20

declare @feedDate datetime
select @feedDate='1/2/2009'

C# プログラムから呼び出すと、パラメーターはSqlCommand.Parametersプロパティを介して渡されます。

この議論の目的のために、パラメーターは決して変化しないと仮定できるため、最適ではないパラメーターの臭いが原因である可能性を排除できます。

4

6 に答える 6

35

OPTION(RECOMPILE) が非常に役立つ状況の優れたリスト (@CodeCowboyOrg によって提供) に追加するには、

  1. テーブル変数。テーブル変数を使用している場合、テーブル変数に対して事前に作成された統計がないため、クエリ プランの推定行と実際の行に大きな違いが生じることがよくあります。テーブル変数を含むクエリで OPTION(RECOMPILE) を使用すると、関連する行数をより適切に見積もったクエリ プランを生成できます。OPTION(RECOMPILE) を追加するまでは、使用できず、放棄するつもりだったテーブル変数を特に重要に使用していました。実行時間は数時間からわずか数分になりました。これはおそらく珍しいことですが、いずれにしても、テーブル変数を使用して最適化に取り組んでいる場合は、OPTION(RECOMPILE) が違いを生むかどうかを確認する価値があります。
于 2015-10-04T01:52:52.753 に答える
3

クエリを調整する前の最初のアクションは、インデックスと統計をデフラグ/再構築することです。そうしないと、時間を無駄にします。

実行計画が安定しているかどうか (パラメーターを変更しても同じ) を確認する必要があります。他のクエリにも役立ちます)。

例として: インデックス idx01_datafeed_trans を作成します datafeed_trans ( feedid, feedDate) INCLUDE( acctNo, tradeDate)

計画が安定している場合、または安定させることができる場合は、sp_executesql('sql 文') を使用して文を実行し、固定の実行計画を保存して使用できます。

計画が不安定な場合は、アドホック ステートメントまたは EXEC('sql 文') を使用して、毎回実行計画を評価および作成する必要があります。(または「再コンパイルを伴う」ストアド プロシージャ)。

それが役に立てば幸い。

于 2015-10-23T12:49:54.487 に答える