ストアドプロシージャの実行が突然遅くなる


15

SQL Server 2000で発生している問題を理解しようとしています。中程度のトランザクションWebサイトでありsp_GetCurrentTransactions、customerIDを受け入れるストアドプロシージャと2つの日付があります。

現在、日付と顧客に応じて、このクエリは0〜1000行の任意の行を返すことができます。

問題:私たちが経験したことはExecution Timeout Expired、特定のクライアントがそのストアドプロシージャを実行しようとすると、突然(通常または同様の)多くのエラーが発生することです。そのため、クエリを調べてSSMSで実行すると、30秒かかることがわかります。したがって、ストアドプロシージャを再コンパイルすると、-bang-が300ミリ秒で実行されます。

私はこれについてDBAに話しました。彼は、ストアドプロシージャを作成したときにデータベースがクエリプランを作成したと言っています。彼は、そのパラメーターセットには良い計画であると言いましたが、特定のパラメーターセットをスローすると、そのデータに最適なプランではなくなるため、実行が遅くなります。

私に提示されたオプションは、問題のクエリをストアドプロシージャから、実行ごとに作成された実行プランを持つ動的SQLに戻すことです。

これは私に一歩後退したような気がし、これを回避する方法があるに違いないと感じています。この問題に対処する他の方法はありますか?

ありとあらゆる回答を歓迎します。


プロシージャにif / elseステートメントがありますか?これは、プランがifステートメントにキャッシュされ、間違ったプランを使用してelseブロックの下で実行しようとすると発生します。これらのエラーは、procの変更に対応していましたか?
ジェレミーグレー

@Jeremy:procに変更はなく、else / ifステートメントもありません。
シアランアーチャー

回答:


14

この問題は、パラメータスニッフィングと呼ばれます。

SQL Serverの以降のバージョンでは、OPTION (RECOMPILE)またはOPTIMIZE FORヒントなど、より多くのオプションを処理できます。

ストアドプロシージャで変数を宣言し、パラメーター値を変数に割り当て、ほとんどの場合合理的に満足のいくプランを得ているかのように聞こえるので、パラメーターの代わりに変数を使用してみてください。

通常、最も壊滅的に悪い計画は、非常に高い選択性を持つパラメーター用にコンパイルされたものですが、低い選択性を持つパラメーターで実行されたものです。

生成されたプランがこのアプローチでより堅牢であり、すべてのパラメーター値で満足であると仮定すると、JNKが提案するアプローチに対するこのアプローチの利点は、呼び出しごとにコンパイルコストが発生しないことです。

欠点は、実行によっては、これらのパラメーター値に合わせて特別に調整されたプランよりも実行時間が長くなる可能性があるため、コンパイル時間と実行時間のトレードオフになることです。


3
またはOracleの用語で「バインド覗き見」
ガイウス

@Gaiusに感謝します。複数のRDBMSの用語を知っておくとよい;)
アンドレイリネア

6

動的SQLを使用する代わりに、proc呼び出しを常に次のように変更できます。

EXEC Database.dbo.usp_Myprocedure 'Parameter' WITH RECOMPILE

WITH RECOMPILE力は(あなたはそれを推測!)、それが実行されるたびに実行計画の再コンパイルを。

WITH RECOMPILEストアドプロシージャの定義に含めることもできます。

CREATE PROCEDURE usp.MyProcedure (Parameters)
WITH RECOMPILE
AS
...

2

また、オプティマイザーと少し戦うことになるので、使用する予定のデータベースを決定することもできます。

テクニックはこれです-ストアドプロシージャを2つに分割し、1つはパラメータのセット、もう1つはパラメータのセットを意味します。それぞれにwhere句を追加して、それらの間で考えられるすべてのケースをカバーします。クエリプランを見てください。1つはパラメーターのセットに対して最適化され、もう1つは他のパラメーターのセットに対して最適化される必要があります。これを実現するためにクエリをいじる必要がある場合があります。または、クエリでこれを実現できない場合があります。その場合、このアプローチは機能しません。

元のストアドプロシージャでパラメータ値を確認し、前の段落の2つのストアドプロシージャの適切な1つにディスパッチします。

これは機能しますが、クエリに対してオプティマイザーをより効果的に機能させるのは一種のハックです。そのようなすべてのハッキングと同様に、データベースの将来のバージョンでは、それは不要であるか、事態を悪化させる可能性さえあります。だから、たとえそれがうまくいったとしても、それが価値があるかどうかを判断する必要があります。



0

うーん...このストアドプロシージャだけに注目している場合、キャッシュされた実行プランを使用すると、表示されている問題が発生することに驚くでしょう。顧客と2つの日付のパラメーターセットを使用して、ストアドプロシージャの実行計画を確認するようにお願いします。より具体的なインデックスが役立つのだろうか-> customerIdなど、2つの日付のみ?


2
なぜ驚きですか?パラメータースニッフィングは、これらの症状のかなり一般的な問題であり、DBAがそれを問題として特定したように見えます。
マーティンスミス

@MartinSmith -私は盗聴PARAMTERを知っているDBAは、再コンパイルのヒントけれども...知らないことを少し驚いている
JNK

@JNK-それは本当です。なぜ彼らがそれを言及しないのかわからない。
マーティンスミス

0

突然のパフォーマンス低下は、おそらく統計の欠落の結果として、効率の悪いクエリプランが作成されたように聞こえます。「エラーと警告」イベントカテゴリを設定してSQL Serverプロファイラーを実行し、統計情報の欠落に関する警告があるかどうかを確認します。

また、インデックスが欠落している場合や、SQL Serverが使用するには断片化されすぎている可能性があるため、インデックスのデフラグが必要になる場合があります。

@JNKはストアドプロシージャについて大きなポイントを挙げます-これらは事前にコンパイルされ、クエリプランはストアドプロシージャと共に格納されます。

WITH RECOMPILEの使用に必ずしも同意しません、クエリプランが保存されて再利用されるという利点が失われます。これが必要な場合がいくつかあります。つまり、基礎となるテーブルの分布統計が呼び出し間で大きく異なる場合、一般に、テーブル内のデータが成熟すると、テーブル内のデータの分布は最小限に変わります。

要約すると、

  1. 欠落している統計を確認します
  2. インデックスの断片化を確認する
  3. ストアドプロシージャを作成して使用する
  4. procの名前を変更してください-sp_は、内部システムのSQL Server procの仮予約されたプレフィックス名前空間です。その結果、SQL Serverは常に最初にそれらのストアドプロシージャのmasterデータベースを検索します。sp_の代わりにproc usp_の名前を変更すると、パフォーマンスが向上しますが、この場合の問題を疑います。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.