2011-12-05 2 views
5

この質問は、私が今までSQL Serverから見た動作であるbizarrestの動作についての解説についての解決策を見つけることではありません。ストアドプロシージャのパフォーマンス - これはWILDですか?

私は、次のシグネチャを持つストアドプロシージャを持っていた: - 約2分のパラメータの特定の集合が与えられる

alter procedure MySP @param1 uniqueidentifier, 
        @param2 uniqueidentifier, 
        @param3 uniqueidentifier 

、このprocが(SqlCommand.ExecuteReader()を使用して)は、C#から実行するには非常に長い時間を取っていました。直接クエリセッションで同じパラメータを使用すると、SPは2秒未満で実行されました。

それは長い時間がかかったし、私も私たちは、このソリューションにつまずいた方法を説明しようとはしませんが、これは我々がやったことです:

SPの冒頭で、我々は3つのローカル変数を宣言し、パラメータの値にそれらを割り当てられ、そのように:その後、

declare @param1_copy uniqueidentifier, 
     @param2_copy uniqueidentifier, 
     @param3_copy uniqueidentifier 

select @param1_copy = @param1, 
     @param2_copy = @param2, 
     @param3_copy = @param3 

そして、SPの残りの部分で、私たちはローカルコピーと入力パラメータへのすべての参照を置換しました。

Voila。 SPは2秒以内に実行されます。そして、ここのチームはうっかりされています。

今、紳士服と紳士は誰でもこの行動を説明できますか?

答えて

8

parameter sniffingのようになります。 Microsoftの定義から

「パラメータスニッフィング」SQL Serverの実行環境は、コンパイルや再コンパイル時に現在のパラメータ値を「盗聴」するプロセスを指し、そして、彼らはそのようクエリオプティマイザに渡し潜在的により高速なクエリ実行計画を生成するために使用できます。 「現在」という語は、コンパイルまたは再コンパイルを引き起こしたステートメント呼び出しに存在するパラメーター値を指します。

すでに1つの修正を考え出したように、別のEXECを使用するように... RECOMPILE WITHだろうルックス:

をEXEC」、非定型パラメータ値でストアドプロシージャを実行すると... WITH RECOMPILE "を使用すると、一般的なパラメータ値を使用してコンパイルされた既存のキャッシュされたプランを最新のクエリプランで置き換えることができます。

+1

素晴らしい。実現せずに教科書のソリューションを見つけました! –

3

私はErland Sommarskogの優れた記事を読むことをお勧めします:Slow in the Application, Fast in SSMS? Understanding Performance Mysteries

この問題に関する詳細は、こちらをご覧ください。

一般に、クエリプランをキャッシュすると、クエリ設定の一部がキャッシュキーで使用されます。これらの設定は、既定の接続文字列とは異なる既定のSSMS設定では異なるため、異なるクエリプランが存在する場合があります。

+0

おそらく、ストアドプロシージャのパラメータとの混同を避けるために、ここでは 'parameter'とは異なる単語を使用するのが最も良いでしょう。 –

+0

@MartinSmith - 公正なポイント。 'settings'に変更 - あなたはどう思いますか? – Oded

+0

私には良く見えます。これらのDMOは 'sys.dm_exec_plan_attributes'で見つかります。 –

0

私はxml型のパラメータを持ち、実行に多くの時間を費やしていたときと同様の状況でした。私は同じアプローチをして、ローカル変数を作成し、パラメータ値を渡しました。それは非常に速く働いていました:)

SQLは、実行計画を作成するためにSPのコンパイルを開始するとき、実行計画に影響を与えます。ただし、パラメータ値をローカル変数に割り当ててSPコード全体でその変数を使用すると、SQLは実行計画に影響を与えるためにパラメータを考慮しないため、クエリからの応答が速くなります。

関連する問題