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


13

あるお客様では、アプリケーションのパフォーマンスに問題があります。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秒未満)します。パラメーターに渡された同じデータを使用して、まったく同じクエリを実行しています。これらのクエリは、主に選択ステートメントを含むストアドプロシージャです。
  • 待機およびキューの統計を調べて、いくつかのリソースで待機しているプロセスがあるかどうかを確認しようとしました。次のクエリを実行しました。

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 Profilerで識別される実行時間の長いステートメントは、複数の結果セット(多くの場合3)を返すストアドプロシージャの呼び出しであることに気付きました。ここで並列問題が発生する可能性はありますか?これが問題の原因であるかどうかを特定する方法はありますか?
  • OLEDBの待機は、リンクサーバーなどのOLEDBリソースの呼び出しが原因で発生する可能性があることをどこかで読みました。インデックスサービスマシン(MSIDXS)に接続するリンクサーバーがありますが、長時間実行されていると識別されたステートメントはいずれもそのリンクサーバーを使用しません。
  • 私が持っている平均待機時間は、LCK_M_Xタイプの待機時間(平均約1.5秒)の方が長くなっていますが、これらの待機タイプは他のタイプと比較してそれほど頻繁に発生しません(たとえば、64 LCK_M_X待機対同じ期間の10,823 CXPACKET待機) )。
  • 私が気づいたことの1つは、MSDTCサービスがクラスター化されていないことです。SQL Serverサービスはクラスター化されますが、MSDTCはクラスター化されません。これによりパフォーマンスが低下することはありますか?アプリはエンタープライズサービス(DCOM)を使用してデータベースにアクセスするため、MSDTCを使用していますが、サーバーはクライアントによってインストールおよび構成されていません。

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

回答:


4

問題の詳細な説明をいただきありがとうございます(実際にレイアウトされた最高の質問の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

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


1

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

例(もちろん単純化):

場合モデル「X」で探したWHERE句製品コードは、特定の値に等しいです。
場合モデル「Y」であった句は、探したところでProductType特定の値に等しいです。

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

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

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

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


exec()関数を使用すると、観察された動作を説明できます。この場合、sp_executesql通常使用すると、動的SQLステートメントの問題が解決されます。
アジェ16

1

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

これらのストアドプロシージャを実行し、実行計画を確認して、ルート演算子(各ステートメントの左端にある緑色のノード)のプロパティを取得します。

実行計画の行の推定数と実際に返された行の数はいくらですか?

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

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

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

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

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


0

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.