web-dev-qa-db-ja.com

統計、実行計画、および「昇順の主要な問題」を理解する

統計、実行計画、ストアドプロシージャの実行の間の関係を(概念的に)よりよく理解しようとしています。

統計はストアドプロシージャの実行プランを作成するときにのみ使用され、実際の実行コンテキストでは使用されないというのは正しいことですか?つまり、これが当てはまる場合、プランが作成されたら(そしてプランが適切に再利用されていると仮定して)、「最新の」統計はどれほど重要ですか。

私が読んだ記事( 統計、行の見積もり、昇順の日付の列 )は、クライアントのデータベースのいくつかで毎日直面しているシナリオと非常によく似たシナリオを説明しているので、特に動機がありました。

特定のストアドプロシージャを使用して定期的にクエリする最大のテーブルの1つに昇順の日付/時刻列があります。

1日に10万行が追加されるときに、実行プランが古くならないようにするにはどうすればよいですか?

この問題に対処するために統計を頻繁に更新する場合、このストアドプロシージャのクエリでOPTION(RECOMPILE)ヒントを使用することは理にかなっていますか?

アドバイスや推奨事項をいただければ幸いです。

Update:SQL Server 2012(SP1)を使用しています。

11
John Russell

統計はストアドプロシージャの実行プランを作成するときにのみ使用され、実際の実行コンテキストでは使用されないというのは正しいことですか?

いいえ、ストアドプロシージャの実行プランがキャッシュされます。プランを保持し続けるのに十分なメモリがあると仮定すると、次のいずれかが発生しない限り、メモリは変更されません(SQL Serverドキュメントの Execution Plan Caching and Reuse から、強調を追加):

  • クエリによって参照されるテーブルまたはビューに加えられた変更(ALTER TABLEおよびALTER VIEW)。
  • キャッシュからそのプロシージャのすべてのプランを削除する単一のプロシージャに加えられた変更(ALTER PROCEDURE)。
  • 実行プランで使用されるインデックスの変更。
  • UPDATE STATISTICSなどのステートメントから明示的に生成されるか、自動的に生成される、実行プランで使用される統計の更新
  • 実行プランで使用されているインデックスを削除する。
  • Sp_recompileへの明示的な呼び出し。
  • キーに対する多数の変更(クエリによって参照されるテーブルを変更する他のユーザーからのINSERTまたはDELETEステートメントによって生成される)。
  • トリガーのあるテーブルで、挿入または削除されたテーブルの行数が大幅に増加した場合。
  • WITH RECOMPILEオプションを使用してストアドプロシージャを実行する。

したがって、統計が更新されると、キャッシュされたプランは自動的に新しい統計を考慮に入れて再コンパイルされます。

1日に10万行が追加されるときに、実行プランが古くならないようにするにはどうすればよいですか?

1つの方法は、上記のように、テーブルに多くの更新がある場合です。数十万の変更された行がこの条件を満たす場合があります。しかし、確実にしたい場合や、より詳細な制御が必要な場合は、統計を更新します。 SQL Serverに統計の自動作成と管理を許可するか、手動で統計を作成できます。どちらの方法についても、詳細情報は SQL Server Auto UpdateおよびAuto Create Statistics Options で確認できます。インデックスを毎週再構築する場合、または再構築すると、プランも更新されるようになります。統計を頻繁に更新すると実際のパフォーマンス結果が得られない可能性があるため、いくつかのテストを行って、何が最も有益かを確認してください。

この問題に対処するために統計を頻繁に更新する場合、このストアドプロシージャのクエリでOPTION(RECOMPILE)ヒントを使用することは理にかなっていますか?

上記の抜粋に基づいて、新しい統計が利用可能になるたびに実行プランが適切に更新されることがわかるため、RECOMPILEを使用するneedはしないでください。 1日の終わりの統計更新で問題ないかもしれませんが(本当に心配している場合)、これまでの発言に基づいて、それが明確に必要であるとは思いません。繰り返しますが、これをテストして、ストアドプロシージャのパフォーマンスに与える影響を確認し、それに応じて計画を立てます。

5
LowlyDBA

統計は実行計画の作成時にのみ使用されると言って間違いありません

いいえ、統計が古くなっていると、影響を受けるステートメントが 最適性関連の再コンパイル になる可能性があります。

定期的にクエリを行う最大のテーブルの1つに昇順の日付/時刻列があります

述語の値が対応する統計ヒストグラムに格納されている値の範囲外(具体的には上)にあるために発生する最適ではない実行計画は、 昇順キー問題 と呼ばれます。統計の再構築は1つの可能な解決策ですが、かなりのリソースを消費する可能性があります。代替案は次のとおりです。

  • トレースフラグ2389および239 。これには、問題のある列を主キーとするインデックスが存在する必要があります。パーティションテーブルでは機能せず、元のカーディナリティエスティメータが使用されている場合、SQL Server 2014でのみ有効です。 トレースフラグ4139 統計オブジェクトが静止している場合も必要になることがあります。

  • SQL Server 2014にアップグレードします。 新しいカーディナリティエスティメーター には、平均密度情報を使用してヒストグラムを超えて推定するロジックが含まれています。これは、一部の重要な状況では2389/2390トレースフラグよりも 精度が低い になることがあります。

  • トレースフラグ2371 を使用して、大きなテーブルのより頻繁な自動統計更新を有効にします。このトレースフラグを使用すると、20%+ 500の変更後に更新するのではなく、 SQRT(1000 * Table rows)変更 のみが必要です。これは、更新がまだ頻繁にトリガーされない可能性があるため、前述のソリューションほど完全なソリューションではありません。

問題の原因が、ヒストグラムを超えた述語値に基づくそれほど頻繁なプランのコンパイルではなく、パラメーターのスニッフィングの結果として、このような悪いプランを時々キャッシュすることの影響についての詳細は、次のことも検討できます。

  • トレースフラグ4136 を使用してパラメータスニッフィングを無効にする
  • OPTIMIZE FOR (@parameter = value)を使用して既知の代表値の計画をコンパイルする
  • OPTIMIZE FOR (@parameter UNKNOWN)を使用して平均分布を使用して最適化する
  • _OPTIMIZE FOR UNKNOWN_の使用(4136と同じですが、クエリごと)
  • OPTION (RECOMPILE)を使用して毎回コンパイルし、特定の値をスニッフィングします。ランタイム値の大部分がヒストグラム内にある場合、これは効果的です。

パラメーターのスニッフィング、埋め込み、および再コンパイルオプションの詳細については、SQLperformance.comの my article を参照してください。

6
Paul White 9