web-dev-qa-db-ja.com

最適化:変数宣言をプロシージャの先頭に移動する

一部のストアドプロシージャの最適化に取り組んでいるとき、私はDBAのところに腰を下ろし、ブロッキングや読み取り/書き込みのアクティビティが高いストアドプロシージャをいくつか試しました。

DBAが言及したことの1つは、再コンパイルを回避するために、ストアドプロシージャの先頭ですべての変数(特にTABLEの変数)を宣言する必要があることです。

これは私がこれを聞いた最初の例であり、私たちが持っているすべての異なるストアドプロシージャを再検討する前に、いくつかの確認を探していました。彼はそれを「コードの遅い閲覧」と呼んでおり、再コンパイルはブロッキングを説明するスキーマをロックしていました。

すべての変数宣言をストアドプロシージャの先頭に移動すると、再コンパイルが減りますか?

15
brad.v

番号。

これは昔は真実でしたが(少なくともSQL Server 2000以降は真実ではありません)、真実ではなかったため、DBAは 次のもの と彼の推奨を混同しました。

ストアドプロシージャの開始時に、一時テーブルのすべてのDDLステートメント(インデックスの作成など)をグループ化することが重要です。これらのDDLステートメントを一緒に配置することで、スキーマの変更による不要なコンパイルを回避できます。

この推奨の背後にある理由の別の説明 このページ を見つけることができます。

this Microsoft KB を見ると、ストアドプロシージャの再コンパイルの原因は次のいずれかであることがわかります(SQL Server 2005以降)。

  1. スキーマが変更されました。
  2. 統計が変更されました。
  3. DNRを再コンパイルします。
  4. 設定オプションが変更されました。
  5. 一時テーブルが変更されました。
  6. リモート行セットが変更されました。
  7. 閲覧権限が変更されました。
  8. クエリ通知環境が変更されました。
  9. MPIビューが変更されました。
  10. カーソルオプションが変更されました。
  11. 再コンパイルオプションあり。

変数の宣言-テーブル変数(つまり@table_variable)-変数を宣言するはDDLとしてカウントされないため、これらのイベントをトリガーできません。変数(テーブル変数も含む)は、T-SQLプログラミング専用に使用される一時オブジェクトです。 テーブル変数は統計を取得しない であり、 トランザクションに拘束されない であるのはそのためです。 変数(テーブルかどうかにかかわらず)を宣言すると、プロシージャの再コンパイルをトリガーできません。

一時テーブルを作成する(つまり、#temp_table)またはインデックス、ただしisデータベースの物理定義に影響するDDL。一時テーブルとインデックスは、統計情報とトランザクション制御を備えた「実際の」オブジェクトであるため、それらを作成すると、上記のリストのイベント1、2、または5のいずれかが発生し、プロシージャの再コンパイルがトリガーされます。

18
Nick Chammas

変数を変更したり、コンパイルロックを減らしたり、スタックの途中または最上位で変数を宣言するための再コンパイルを減らしたりしてはなりません。私は、読みやすさのために、多くの場合、これを一番上で行います。

質問の「私のDBAの考えは何か」の部分にたどり着くために、私が思いつくことができる唯一のことは、(何かが以前はどうだったかについて考えているというニックの点を除いて)おそらく、パラメータスニッフィング(このときのオプション2 リンク 簡単な話)

ブロッキングについて->真のブロッキングが表示されている場合は、DBAが話している可能性が高いコンパイルロックの競合ではありません。これに影響する特定の事項があることは事実ですが(たとえば、スキーマ修飾テーブルではなく、ストアドプロシージャコールのスキーマ修飾ではありません)、これは確実に高読み取りの原因ではなく、おそらくブロックの原因ではありません。これらのコンパイルロックを回避するために、できる限りのことを行ってください。ただし、残りのストアドプロシージャコードのチューニングと最適化は、変数の場所を気にすることよりも重要なタスクであると考えます。ここで問題が発生していないことを確認したい場合は、 コンパイルロックを識別して解決する方法 を読むこともできます。

これらの前後の例を投稿してください。DBAがここで推進していることがわかります。

3
Mike Walsh