web-dev-qa-db-ja.com

SQLサーバーのCPU使用率が高い-クエリが遅い

MS SQL Serverは、CPUパワーの約95%を使用しています。

サーバー(ハードウェア)の再起動後、またはSQLサービスの再起動後、使用率は0%で、1〜3日かけてゆっくりと増加します。使用量によって異なります。

80%を超えると、すべてのクエリが非常に遅くなります。

私たちのウェブサイトは多くの大きなクエリを扱っているので、それらのいくつかは45-60秒かかります。再起動後(CPU使用率が80%未満)、同じクエリで11〜20秒かかります。


どうすれば修正できますか?アフィニティマスクでCPU使用率を調整できることをオンラインで読みましたが、アフィニティ設定が無効になっています。変更できません。 これはプロセッサが1つしかないためですか?

クエリ自体にはたくさんのコツがありますが、私たちのWebサイトとサービスは非常に大きく、変更するのが多すぎます。

それらのほとんどはすでにかなり最適化されています。


2秒しかかかりませんが、SQLサービスの再起動を続けることができません。ユーザーが電話をかけてメッセージを録音できるアラームサービスがあるため、選択したグループが呼び出され、録音されたメッセージが聞こえます。

このシステムは何百人もの捜索救助チームによって使用されており、SQLサービスがアラーム中に再起動した場合、システムは終了し、呼び出した人には通知されません。


あちこち検索してみましたが、「アフィニティマスク」以外は変更できません。

現在のクエリを終了せずに、CPUキャッシュをクリアする方法が必要です...そうですか?


SQL: Microsoft SQL Server 11.0.2100.60
OS: Windows Server 2012 x64
Processor: 2.30 GHz
RAM: 4.00 GB
11
Levi Johansen

これはロングショットですが、強制パラメーター化設定を確認することをお勧めします。パフォーマンスが悪いときに多数のクエリプランが表示される場合、クエリは期待どおりにキャッシュされておらず、クエリは、キャッシュをスキャンして、すでに使用する予定があるかどうかを確認するのに長い時間がかかります。キャッシュをクリアするとこの問題が解決する場合は、強制パラメーター化設定の変更を検討することをお勧めします。以下を使用してキャッシュをクリアできます。

DBCC FREEPROCCACHE

キャッシュのクリアが機能した場合は、次のようにして強制パラメーター化設定を確認できます。

SELECT name
     , is_parameterization_forced
  FROM sys.databases;

これはおそらくデフォルトの0に設定されています。彼らが望むなら、あなたはそれをtrueに設定することができます:

ALTER DATABASE [database_name] SET PARAMETERIZATION FORCED;

これは最初に開発環境で行う必要がありますそして、これが他の方法でデータベースに悪影響を及ぼすかどうかを確認します。以下を使用して元に戻すことができます:

ALTER DATABASE [database_name] SET PARAMETERIZATION SIMPLE;
7
Drew Leffelman

アフィニティは「CPU使用率を調整する」ことはできません(たとえば、CPUの処理を減らします)。これにより、CPUをオフにする(おそらく同じマシン上の別のインスタンスで使用できるようにする)か、CPUをI/Oのみで支援します。複数のCPUがあったとしても、前者を使用して目標を達成することはできません。また、CPU使用率を高くしている原因がわからないため、後者を推測することはできません。それは、非常に貧弱なインデックス作成、過度のコンパイル、豊富なスカラーUDF、I/Oスラッシングが原因である可能性があります。 (そして、I/Oが原因である可能性のある理由は、データベースが3 GB程度かそれ以上の場合、データをバッファプールメモリとの間で常に入れ替える必要があり、CPUに負荷がかかるためです。)

CPUキャッシュも、ダウンする必要がないうさぎの穴です。 CPUキャッシュに問題があるため、CPUが95%でスラッシングしていることは間違いありません。

CPUプレッシャーの原因を絞り込むのに役立ち、ストアドプロシージャを使用していると想定すると、Glenn Berryからのこの診断クエリを確認できます( ここからソース )-必ず実行してください適切なデータベースのコンテキスト:

-- Top Cached SPs By Total Worker time (SQL Server 2012). 
-- Worker time relates to CPU cost  (Query 44) (SP Worker Time)

SELECT TOP (25) 
  p.name AS [SP Name], 
  qs.total_worker_time AS [TotalWorkerTime], 
  qs.total_worker_time/qs.execution_count AS [AvgWorkerTime], 
  qs.execution_count, 
  ISNULL(qs.execution_count/DATEDIFF(Second, qs.cached_time, GETDATE()), 0) 
    AS [Calls/Second],
  qs.total_elapsed_time, 
  qs.total_elapsed_time/qs.execution_count AS [avg_elapsed_time], 
  qs.cached_time
FROM sys.procedures AS p WITH (NOLOCK)
INNER JOIN sys.dm_exec_procedure_stats AS qs WITH (NOLOCK)
ON p.[object_id] = qs.[object_id]
WHERE qs.database_id = DB_ID()
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

-- This helps you find the most expensive cached stored procedures from a CPU perspective
-- You should look at this if you see signs of CPU pressure

ストアドプロシージャを使用していない場合、John Samsonの次の例は、アドホッククエリを分離するのに役立ちます( ここからソース )。

SELECT TOP (25)
    qs.sql_handle,
    qs.execution_count,
    qs.total_worker_time AS Total_CPU,
    total_CPU_inSeconds = --Converted from microseconds
    qs.total_worker_time/1000000,
    average_CPU_inSeconds = --Converted from microseconds
    (qs.total_worker_time/1000000) / qs.execution_count,
    qs.total_elapsed_time,
    total_elapsed_time_inSeconds = --Converted from microseconds
    qs.total_elapsed_time/1000000,
    st.text,
    qp.query_plan
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
CROSS apply sys.dm_exec_query_plan (qs.plan_handle) AS qp
ORDER BY qs.total_worker_time DESC OPTION (RECOMPILE);

Adam Machanicの sp_WhoIsActive もご覧ください。これは、現在実行中のすべてのクエリをすばやく分析し、必要に応じて並べ替えることができるストアドプロシージャです(例:@sort_order = '[CPU] DESC')。

ただし、特にこれが本当に捜索救助チームにとってミッションクリティカルである場合、私が最初に行うことは、より優れたハードウェアを購入することです。より多くのCPUとより多くのRAMが必要です。また、より良い高可用性(たとえば、クラスタリング、ミラーリング、または可用性グループ)も絶対に必要です。)物理マシンの再起動の理由はありませんアプリケーションを完全にオフラインにする必要があります-その問題に対するより良い解決策があります。最後に、この「サーバー」には1つのディスクドライブしかないと思います。つまり、OSから、SQL Serverデータファイルから、すべてのI/Oがログに記録されます。ファイル、tempdbなどはすべて、単一のコントローラーを経由して、単一のドライブで読み取り/書き込みアクティビティを共有します。より多くのディスクを取得します。可能な場合は、SSDを取得します。RAIDを使用して、I/Oをできるだけ分散させます。

とはいえ、問題にハードウェアを投入することだけが修正の一部になるわけではありません。過度のCPU使用率を引き起こしている原因を正確に特定し、使用しているハードウェアに関係なく、それらの問題を攻撃する必要があります。

他のアイデアについては、このStackOverflowの質問もご覧ください。

https://stackoverflow.com/questions/945063/how-do-i-find-out-what-is-hammering-my-sql-server

18
Aaron Bertrand

次の提案は、実際のコードが見えないため、「暗闇の中でのショット」です。

まず、SPはカーソルを開いたままにしている可能性があります。カーソル、特にCloseとDeallocateを確認してください。誰かが閉じている可能性がありますが、カーソルの割り当てを解除していません。アップグレードすると、2012は残りのカーソルを2008 R2とは異なる方法で処理する可能性があります。

2つ目は、クリアされないテーブルロックが存在する可能性があることです。繰り返しになりますが、わかりませんが、「トランザクションの開始」の後に誰かがグローバル一時テーブルを作成し、「トランザクションの終了」が実行されないか、ストアドプロシージャが失敗してロックされたままになります。 tempdbのスペースを占めるテーブル。

たまたまWinLinkを使っていますか?これについての何かは、漠然と聞き覚えがあります。

0
Meredith Poor