同じSQL Server 2005インスタンスで2つのほぼ同じクエリを実行しています。
SELECT
クエリです(私は知っています...私はアプリケーション開発者ではなく、DBAだけです)。OPTION (RECOMPILE)
が追加されています。他には何も変更されていません。
最初のものは、実行するたびに55秒かかります。
2つ目は2秒かかります。
両方の結果セットは同じです。
このヒントによってパフォーマンスが劇的に向上するのはなぜですか?
RECOMPILE
のBooks Onlineエントリには、あまり詳細な説明はありません。
SQL Serverデータベースエンジンに、クエリの実行後に生成されたプランを破棄するように指示します。クエリオプティマイザーは、同じクエリが次に実行されるときにクエリプランを再コンパイルする必要があります。 RECOMPILEを指定しない場合、データベースエンジンはクエリプランをキャッシュして再利用します。クエリプランをコンパイルするとき、RECOMPILEクエリヒントはクエリ内のローカル変数の現在の値を使用し、クエリがストアドプロシージャ内にある場合は、現在の値が任意のパラメーターに渡されます。
RECOMPILEは、ストアドプロシージャ全体ではなく、ストアドプロシージャ内のクエリのサブセットのみを再コンパイルする必要がある場合に、WITH RECOMPILE句を使用するストアドプロシージャを作成する便利な代替手段です。詳細については、「ストアドプロシージャの再コンパイル」を参照してください。 RECOMPILEは、計画ガイドを作成するときにも役立ちます。詳細については、「プランガイドを使用したデプロイ済みアプリケーションのクエリの最適化」を参照してください。
私のクエリには多くのローカル変数があるため、OPTION (RECOMPILE)
クエリヒントを使用すると、SQL Serverが(真剣に)最適化できると思います。
どこでも、OPTION (RECOMPILE)
は避けるべきだと人々が言っているのを見ています。これについての説明は、一般に、このヒントを使用すると、SQL Serverはこの実行計画を再利用できないため、毎回再コンパイルして時間を浪費する必要があるということです。
(しかし)巨大なパフォーマンス上の利点を考えると、このクエリヒントを使用することが今回は良いことだと思う傾向があります。
使用すべきですか?そうでない場合、このヒントなしで、アプリケーションを変更せずに、SQL Serverがより適切な実行プランを使用できるようにする方法はありますか?
記事に記載されているように Microsoft SQL Server 2005のクエリオプティマイザーで使用される統計
パラメータやリテラルの代わりにクエリ述語でローカル変数を使用する場合、オプティマイザは質の低い推定、または述語の選択性の推測に頼ります。ローカル変数の代わりにクエリでパラメーターまたはリテラルを使用する
オプティマイザが列の使用可能な統計をまったく持たない場合、 推測=
述語は行の10%、BETWEEN
9%に一致し、>, >=, < and <=
は30%に一致します。利用可能な列統計がある場合、=
述語は以下のように異なる方法で処理されます。
クエリでローカル変数が使用されている場合でも、等価述語の場合、推測よりも優れた推定が使用されます。 "
@local_variable = column_name
"形式の条件の選択性は、column_nameのヒストグラムからの平均値頻度を使用して推定されます。したがって、たとえば、列column_nameにすべての一意の値が含まれている場合、選択性推定値1/(number of unique values in column)
が使用されますが、これは正確です。
したがって、これはOPTIMIZE FOR (UNKNOWN)
を使用するのと基本的に同じです。単純な10%
推測よりも正確である可能性がありますが、クエリしている特定の値に合わせて調整されていません。
SQL Serverが実行されるたびにクエリを最適化し、ローカル変数の値を使用してクエリの最適化中に基数とコストを推定するには、クエリに
RECOMPILE
クエリヒントを追加します。
RECOMPILE
を使用すると、おそらくより正確なカーディナリティの見積もりが得られるため、実際のクエリのさまざまな部分から返される行の数により適した、結合順序/結合タイプを含む別のプランが得られます。