1

ここ数週間、サーバーで進行中の問題と戦っています。いくつかの異なるストアド プロシージャで実行される単純なクエリがありますが、そのうちのいくつかでは、クエリの実行に 4 分近くかかる場合があります。一部のプロシージャには、これとまったく同じクエリがあり、1 秒未満で実行されます。クエリ ウィンドウから実行すると、1 秒未満で戻ります。

これを再現できません - ユーザーが実行している手順を実行できません (データが変更されるため)。テスト サーバーでは問題は発生しません。実行計画を再作成しているように見えるプロシージャを再コンパイル (F5) して、しばらく修正することもできますが、常に戻ります。

クエリは次のように単純です。

SELECT '1' 
FROM TRANSACTION_LOG WITH (NOLOCK) 
WHERE TYPE = 15 AND SERIAL_NO = @P_TRAVELER_SERIAL
  • TRANSACTION_LOG〜90m行あります
  • TYPE非クラスター化インデックスがある
  • SERIAL_NO非クラスター化インデックスがある

いくつかの調査とプロファイラによるキャプチャの後、実行計画に奇妙な点が見つかりました。実行計画が速く実行されているときと、実行が遅いときの別の実行計画をキャプチャすることができました。これらは、まったく同じ手順、まったく同じクエリからのものです。唯一の違いは、@P_TRAVELER_SERIALパラメーターの値です。

速い:

Compute Scalar(DEFINE:([Expr1005]=CASE WHEN [Expr1006] THEN (1) ELSE (0) END))          
  |--Nested Loops(Left Semi Join, DEFINE:([Expr1006] = [PROBE VALUE]))
    |--Constant Scan
    |--Filter(WHERE:([MICS].[dbo].[Transaction_Log].[TYPE]=(15)))
      |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000], [Expr1010]) WITH UNORDERED PREFETCH)
        |--Index Seek(OBJECT:([MICS].[dbo].[Transaction_Log].[IX_SERIAL_NO]), SEEK:([MICS].[dbo].[Transaction_Log].[SERIAL_NO]=[@P_TRAVELER_SERIAL]) ORDERED FORWARD)
        |--RID Lookup(OBJECT:([MICS].[dbo].[Transaction_Log]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD)

スロー:

Compute Scalar(DEFINE:([Expr1005]=CASE WHEN [Expr1006] THEN (1) ELSE (0) END))
  |--Nested Loops(Left Semi Join, DEFINE:([Expr1006] = [PROBE VALUE]))
    |--Constant Scan 
    |--Table Scan(OBJECT:([MICS].[dbo].[Transaction_Log]), WHERE:([MICS].[dbo].[Transaction_Log].[TYPE]=(15) AND [MICS].[dbo].[Transaction_Log].[SERIAL_NO]=[@P_TRAVELER_SERIAL]))

1 つのプランでインデックス シークを使用し、もう 1 つのプランでテーブル スキャンを使用するのはなぜですか? 同じクエリで同じ手順ですか?テーブルのアクティビティはそれと関係がありますか? 賑やかな食卓です…

ありがとう

4

1 に答える 1

1

これは、パラメーターのスニッフィングの問題のように思えます。時間が経つにつれて、SQL Server はプロシージャの実行計画が古くなっていると判断し、次にプロシージャが実行されたときに新しい計画がコンパイルされます。残念ながら、これが発生すると、SQL サーバーは、プロシージャに対して生成 (およびキャッシュ) するプランを決定するときに、現在渡されている値を使用します。その時点で渡された値があまり一般的でない場合、SQL Server はテーブル スキャンを行う実行プランを構築し、その後キャッシュすることがあります。これは、渡された珍しい値には最適かもしれませんが、インデックス シークの恩恵を受ける値には明らかに理想的ではありません。

詳細と考えられる回避策については、この technet ブログ投稿を参照してください。 http://blogs.technet.com/b/mdegre/archive/2012/03/19/what-is-parameter-sniffing.aspx

于 2012-09-07T03:43:04.953 に答える