web-dev-qa-db-ja.com

SQL Server 2008 R2でSQL Serverステートメントが断続的に遅くなる

あるお客様では、アプリケーションのパフォーマンスに問題が発生しています。これは、SQL Serverデータベースのデータを消費および更新する.NET 3.5 Webアプリです。現在、本番環境は、フロントエンドとしてのWindows 2008 R2マシンと、バックエンド上のSQL Server 2008 R2クラスターで構成されています。私たちのアプリはCOM +とMSDTCを使用してデータベースに接続します。

状況は次のとおりです。エンドユーザーがアプリケーションの速度低下を訴える場合があります。一部のページは、予想よりもロードに時間がかかります。何が起こっているのかを理解しようとしているときに、パフォーマンスの低下の原因である可能性のあるデータベース側の奇妙な動作を見つけることができました。予想されるよりも実行に時間がかかるSQLステートメントが時々あることに気づきました。プロファイラートレース(TSQL_Durationテンプレートを使用)を使用してこれらのステートメントの一部(主にアプリケーションのストアドプロシージャの呼び出し)を特定し、長時間実行されているクエリを特定しました。

問題は、これらのストアドプロシージャをSQL Management Studioのデータベースで直接実行すると、時間がかかる(約7/8秒)か、速くなる(1秒未満)ことです。 SQLマシン(4コア、32 GB)が他のアプリケーションで使用されておらず、これらのクエリの実行にこれほど長い時間がかかることはないため、これが発生する理由はわかりません。

私はDBAやSQL Serverの第一人者ではないので、問題を理解するのに役立つ可能性のあるものをいくつか調べてみました。問題を解決するために私が取った手順と、これまでにわかったことは次のとおりです。

  • アプリケーションによって呼び出されるすべてのTSQLコードは、ストアドプロシージャで記述されています。
  • SQL Serverプロファイラーで長時間実行されているクエリの一部を特定しましたが、これらをManagement Studioで実行すると、実行に時間がかかる(4〜10秒)か、すばやく実行される(1秒未満)かのいずれかです。パラメータで渡された同じデータでまったく同じクエリを実行しています。これらのクエリは主に、selectステートメントを含むストアドプロシージャです。
  • 待機とキューの統計を見て、いくつかのリソースで待機しているプロセスがあるかどうかを調べてみました。次のクエリを実行しました。
WITH Waits AS
    (SELECT
        wait_type,
        wait_time_ms / 1000.0 AS WaitS,
        (wait_time_ms - signal_wait_time_ms) / 1000.0 AS ResourceS,
        signal_wait_time_ms / 1000.0 AS SignalS,
        waiting_tasks_count AS WaitCount,
        100.0 * wait_time_ms / SUM (wait_time_ms) OVER() AS Percentage,
        ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS RowNum
    FROM sys.dm_os_wait_stats
    WHERE wait_type NOT IN (
        'CLR_SEMAPHORE', 'LAZYWRITER_SLEEP', 'RESOURCE_QUEUE', 'SLEEP_TASK',
        'SLEEP_SYSTEMTASK', 'SQLTRACE_BUFFER_FLUSH', 'WAITFOR', 'LOGMGR_QUEUE',
        'CHECKPOINT_QUEUE', 'REQUEST_FOR_DEADLOCK_SEARCH', 'XE_TIMER_EVENT',  'BROKER_TO_FLUSH',
        'BROKER_TASK_STOP', 'CLR_MANUAL_EVENT', 'CLR_AUTO_EVENT',     'DISPATCHER_QUEUE_SEMAPHORE',
        'FT_IFTS_SCHEDULER_IDLE_WAIT', 'XE_DISPATCHER_WAIT', 'XE_DISPATCHER_JOIN', 'BROKER_EVENTHANDLER',
        'TRACEWRITE', 'FT_IFTSHC_MUTEX', 'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
        'BROKER_RECEIVE_WAITFOR', 'ONDEMAND_TASK_QUEUE', 'DBMIRROR_EVENTS_QUEUE',
        'DBMIRRORING_CMD', 'BROKER_TRANSMITTER', 'SQLTRACE_WAIT_ENTRIES',
        'SLEEP_BPOOL_FLUSH', 'SQLTRACE_LOCK')
    )
SELECT
    W1.wait_type AS WaitType, 
    CAST (W1.WaitS AS DECIMAL(14, 2)) AS Wait_S,
    CAST (W1.ResourceS AS DECIMAL(14, 2)) AS Resource_S,
    CAST (W1.SignalS AS DECIMAL(14, 2)) AS Signal_S,
    W1.WaitCount AS WaitCount,
    CAST (W1.Percentage AS DECIMAL(4, 2)) AS Percentage,
    CAST ((W1.WaitS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgWait_S,
    CAST ((W1.ResourceS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgRes_S,
    CAST ((W1.SignalS / W1.WaitCount) AS DECIMAL (14, 4)) AS AvgSig_S
FROM Waits AS W1
    INNER JOIN Waits AS W2 ON W2.RowNum <= W1.RowNum
GROUP BY W1.RowNum, W1.wait_type, W1.WaitS, W1.ResourceS, W1.SignalS, W1.WaitCount,    W1.Percentage
HAVING SUM (W2.Percentage) - W1.Percentage < 95; -- percentage threshold
GO

これが私が見つけたものです:

  • DBCC SQLPERFを使用して統計情報をリセットした後(約1または2時間後)、最も多くの待機タイプはSOS_SCHEDULER_YIELDおよびWRITELOGです。
  • 時間の経過(約1日の実行後)において、データベースで最も発生する待機タイプは、CXPACKET(67%)とOLEDB(17%)ですが、それぞれの平均待機時間は長くありません。また、SQLプロファイラーで識別される実行時間の長いステートメントが、複数の結果セット(多くの場合3)を返すストアドプロシージャの呼び出しであることにも気付きました。ここでパラレリズムの問​​題はありますか?これが問題の原因かどうかを特定する方法はありますか?
  • OLEDBの待機はリンクサーバーのようなOLEDBリソースへの呼び出しが原因で発生する可能性があることをどこかで読んだことがあります。インデックスサービスマシン(MSIDXS)に接続するためのリンクサーバーはありますが、長時間実行されていると識別されたステートメントは、そのリンクサーバーを使用しません。
  • LCK_M_Xタイプの待機(平均約1.5秒)の平均待機時間は長くなっていますが、これらの待機タイプは、他のタイプと比べてそれほど頻繁には発生しません(たとえば、同じ期間に64 LCK_M_X待機vs 10,823 CXPACKET待機) )。
  • MSDTCサービスがクラスター化されていないことに気付きました。 SQL Serverサービスはクラスター化されていますが、MSDTCではありません。このため、パフォーマンスが低下する可能性はありますか?私たちのアプリはデータベースへのアクセスにエンタープライズサービス(DCOM)を使用していますが、サーバーは私たちではなくクライアントによってインストールおよび構成されなかったため、MSDTCを使用しています。

誰かがこのデータをもっと理解するのを手伝ってくれる?誰が何が起こっているのか理解する手助けをしてくれますか?サーバーで何かを試して理解するためにできることはありますか?アプリケーション開発チームに相談する必要がありますか?

13
Joao Maia

問題の詳細な説明(実際に最もよくレイアウトされた質問の1つ)をありがとうございます。

WRITELOGは非常に一般的なタイプの待機なので、心配する必要はありません。 SOS_SCHEDULER_YIELDを見ると、CPUプレッシャーとCXPACKETが示されているため、いくつかのインデックスが欠落している可能性があり、OLTPシステムのクエリから多くのデータを取得している可能性があります。 Missing Indexes DMVを調べて、疑わしいprocにインデックスがあるかどうかを確認します(ほとんど確実に少ないでしょう)。

http://sqlfool.com/2009/04/a-look-at-missing-indexes/

http://troubleshootingsql.com/2009/12/30/how-to-find-out-the-missing-indexes-on-a-sql-server-2008-or-2005-instance-along- with-the-create-index-commands /

これに関するsqlblog.comのJonathan Kehayiasの投稿も探してください。

また、パラメータスニッフィングもご覧ください。

http://sommarskog.se/query-plan-mysteries.html

http://pratchev.blogspot.com/2007/08/parameter-sniffing.html

それはあなたのニーズに対する完全な答えではありませんが、良い出発点です。詳細が必要な場合はお知らせください。

4
Sankar Reddy

従業員の1人がいくつかのストアドプロシージャを書き直した後も、同様の問題が発生しました。過剰な分岐があり、動的SQLが作成されているため、where句が大幅に変更されていることがわかりました。

たとえば(もちろん簡略化):

Modelが "X"の場合、where句はProductCodeを探して特定の値と等しくなります。
Modelが "Y"の場合、where句はProductTypeを探して特定の値と等しくなります。

SQL Serverは、ストアドプロシージャが初めて実行されるときに、入力パラメーターに基づいてクエリプランを構築します。したがって、クエリプランが「ProductCode」の等しいを使用するロジックに基づいて構築されており、「ProductType」の等しいを要求している場合、クエリプランは一致せず、ほとんどの場合、フルテーブルスキャンが行われます。

ストアドプロシージャの上部に「WITH RECOMPILE」を配置してみてください。 CREATE PROCEDURE(Transact-SQL)

これを説明する最良の方法は次のとおりです。

姓でソートされた名前と電話番号のリストがあるとします。これは、姓(姓に基づくクエリプラン)を使用している人を見つけるのに最適です。ここで、市外局番203のすべての名前と電話番号が必要であるとします。リストが姓で並べ替えられている場合、市外局番203のすべての人の完全なリストを取得する唯一の方法は、上から始めて、順番に読むことです。すべてのレコード。 (全表スキャン)。

SSMSとアプリでクエリが断続的に高速かつ低速で実行されている場合は、統計情報またはパラメータースニッフィングの問題がある可能性があります。

これらのストアドプロシージャを実行し、実行プランを確認して、ルートオペレーターのプロパティ(各ステートメントの左端にある緑のノード)をプルアップします。

実際に返された行数に対して、実行プランの推定行数はいくつですか?

コンパイルされたパラメータは実際のクエリパラメータと一致しますか?

少数の行のみを返すパラメーターの実行プランが作成され、膨大な数の行を返すパラメーターを使用して同じ手順を実行すると、SQLはクエリに対して誤った実行プランを使用する場合があります。

実行プランの選択はSQL統計と密接に関連しているため、定期的に統計を再構築することをお勧めします。

提供されたパラメーターに応じて、少量のデータまたは大量のデータを返すストアード・プロシージャーがある場合、パラメーターのスニッフィングの問題がある可能性があります。

統計を再構築しても問題が解決しない場合は、OPTION (RECOMPILE)を使用して、ストアドプロシージャで最も高価なステートメントを実行できます。

1
Andre Ranieri

長時間実行されているクエリを特定したので、これらのプロシージャの実行プランをキャッシュからフェッチし、そこで問題を特定できるかどうかを確認できます。多くの場合、データ型の暗黙的または実行時の変換があります。また、大量のデータをパージまたは挿入する場合は、統計も更新することをお勧めします。

0
Chandan jha