質問
CPU使用率の内訳を取得することはできますか データベースによる?
理想的には、SQLサーバー用のタスクマネージャータイプのインターフェイスを探していますが、各PIDのCPU使用率を調べる代わりに(次のように) taskmgr
) または各 SPID (例: spwho2k5
)、各データベースの合計 CPU 使用率を表示したいと考えています。単一の SQL インスタンスを想定します。
このデータを収集してレポートするためのツールを作成できることはわかっていますが、どのデータベースがデータに最も貢献しているかをライブビューで確認できるツールはあるのだろうかと疑問に思っています。 sqlservr.exe
CPU負荷。
解決
ある意味。このクエリを確認してください:
SELECT total_worker_time/execution_count AS AvgCPU
, total_worker_time AS TotalCPU
, total_elapsed_time/execution_count AS AvgDuration
, total_elapsed_time AS TotalDuration
, (total_logical_reads+total_physical_reads)/execution_count AS AvgReads
, (total_logical_reads+total_physical_reads) AS TotalReads
, execution_count
, SUBSTRING(st.TEXT, (qs.statement_start_offset/2)+1
, ((CASE qs.statement_end_offset WHEN -1 THEN datalength(st.TEXT)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2) + 1) AS txt
, 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 1 DESC
これにより、プラン キャッシュ内のクエリが、消費された CPU 量の順に取得されます。SQL エージェント ジョブのように、これを定期的に実行し、結果をテーブルに挿入して、再起動後もデータが保持されることを確認できます。
結果を読めば、なぜそのデータを個々のデータベースに直接関連付けることができないのかがわかるでしょう。まず、次のようなトリックを実行することで、単一のクエリで実際のデータベースの親を隠すこともできます。
USE msdb
DECLARE @StringToExecute VARCHAR(1000)
SET @StringToExecute = 'SELECT * FROM AdventureWorks.dbo.ErrorLog'
EXEC @StringToExecute
クエリは MSDB で実行されますが、結果は AdventureWorks からポーリングされます。CPU 消費量をどこに割り当てればよいでしょうか?
次のような場合、事態はさらに悪化します。
- 複数のデータベース間の結合
- 複数のデータベースでトランザクションを実行し、ロック作業が複数のデータベースにまたがる
- MSDB で「動作」する SQL エージェント ジョブを MSDB で実行しますが、個々のデータベースをバックアップします。
それは延々と続きます。このため、データベース レベルではなくクエリ レベルでパフォーマンスを調整することが合理的です。
SQL Server 2008R2 で Microsoft は、単一のデータベースを分散および展開可能な DAC パックにパッケージ化できるパフォーマンス管理機能とアプリ管理機能を導入しました。これらは、個々のデータベースとそのアプリケーションのパフォーマンス管理を容易にする有望な機能です。ただし、それでもあなたが探していることは実現しません。
さらに詳しく知りたい場合は、以下をチェックしてください。 Toad World の SQL Server wiki (以前は SQLServerPedia) の T-SQL リポジトリ.
1 月 29 日に更新され、単なる平均ではなく合計数が含まれるようになりました。
他のヒント
SQL Server (2000 以降) では、パフォーマンス カウンター (パフォーマンス モニターまたは Perfmon から表示可能) がインストールされます。
カウンターカテゴリの1つ(SQL Server 2005のインストールからIS :) -SQLServer:データベース
各データベースに 1 つのインスタンスを使用します。ただし、使用可能なカウンターには、CPU % 使用率カウンターなどは提供されていませんが、CPU の適切な推定値を取得するために使用できるレート カウンターはいくつかあります。たとえば、2 つのデータベースがあり、測定されたレートがデータベース A では 20 トランザクション/秒、データベース B では 80 トランザクション/秒である場合、A が合計 CPU のおよそ 20% に寄与していることがわかります。 B は残りの 80% に寄与します。
ここにはいくつかの欠陥があります。これは、実行されるすべての作業が CPU に依存していることを前提としているためです。もちろん、データベースの場合はそうではありません。しかし、それが始まりになると私は信じています。
高負荷を引き起こしている実際のデータベースを表示するクエリを次に示します。これはクエリ キャッシュに依存しており、メモリ不足のシナリオでは頻繁にフラッシュされる可能性があります (クエリの有用性が低下します)。
select dbs.name, cacheobjtype, total_cpu_time, total_execution_count from
(select top 10
sum(qs.total_worker_time) as total_cpu_time,
sum(qs.execution_count) as total_execution_count,
count(*) as number_of_statements,
qs.plan_handle
from
sys.dm_exec_query_stats qs
group by qs.plan_handle
order by sum(qs.total_worker_time) desc
) a
inner join
(SELECT plan_handle, pvt.dbid, cacheobjtype
FROM (
SELECT plan_handle, epa.attribute, epa.value, cacheobjtype
FROM sys.dm_exec_cached_plans
OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
/* WHERE cacheobjtype = 'Compiled Plan' AND objtype = 'adhoc' */) AS ecpa
PIVOT (MAX(ecpa.value) FOR ecpa.attribute IN ("dbid", "sql_handle")) AS pvt
) b on a.plan_handle = b.plan_handle
inner join sys.databases dbs on dbid = dbs.database_id
あなたの質問に対する答えはノーだと思います。
問題は、マシン上の 1 つのアクティビティによって複数のデータベースに負荷がかかる可能性があることです。構成 DB からの読み取り、ログ DB へのログ記録、およびタイプに基づいてさまざまな DB へのトランザクションの出入りを行うプロセスがある場合、CPU 使用率をどのように分割すればよいですか?
CPU 使用率をトランザクション負荷で割ることもできますが、これもまた大まかな指標であり、誤解を招く可能性があります。たとえば、トランザクション ログの配布をある DB から別の DB に分割するにはどうすればよいでしょうか?CPUに負荷がかかっているのは読み込み時でしょうか、それとも書き込み時でしょうか?
マシンのトランザクション レートと、それによって引き起こされる CPU 負荷を確認することをお勧めします。ストアド プロシージャのプロファイルを作成し、過度に時間がかかっているものがないかどうかを確認することもできます。ただし、これでは希望する答えは得られません。
上記すべてを念頭に置いて。
SQL Server 2012 (2008 になるかも?) 以降、列が追加されました。 データベースID で sys.dm_exec_sessions.
各データベースの CPU を簡単に計算できます。 現在接続されています セッション。セッションが切断された場合、その結果は失われます。
select session_id, cpu_time, program_name, login_name, database_id
from sys.dm_exec_sessions
where session_id > 50;
select sum(cpu_time)/1000 as cpu_seconds, database_id
from sys.dm_exec_sessions
group by database_id
order by cpu_seconds desc;
を見てみましょう SQLセントリー. 。必要なことはすべて、それ以上のことができます。
よろしく、リーベン
SQLプロファイラーを見たことがありますか?
標準の「T-SQL」または「ストアド プロシージャ」テンプレートを使用し、フィールドを微調整してデータベース ID でグループ化します (数値を使用する必要があると思います。データベース名は取得できませんが、exec sp_databases を使用すると簡単に見つけることができます)リストを取得するには)
これをしばらく実行すると、合計 CPU 数 / ディスク IO / 待機数などが表示されます。これにより、各データベースで使用されている CPU の割合がわかります。
PerfMon カウンタを同時に監視し (SQL データベースにデータを記録)、SQL プロファイラに対して同じことを実行すると (データベースに記録)、 5月 2 つを相互に関連付けることができます。
それでも、どの DB をより詳細に検討する価値があるかについて十分な手がかりが得られるはずです。次に、そのデータベース ID だけを使用して同じことをもう一度実行し、最も高価な SQL / ストアド プロシージャを探します。
このクエリを確認してください:
SELECT
DB_NAME(st.dbid) AS DatabaseName
,OBJECT_SCHEMA_NAME(st.objectid,dbid) AS SchemaName
,cp.objtype AS ObjectType
,OBJECT_NAME(st.objectid,dbid) AS Objects
,MAX(cp.usecounts)AS Total_Execution_count
,SUM(qs.total_worker_time) AS Total_CPU_Time
,SUM(qs.total_worker_time) / (max(cp.usecounts) * 1.0) AS Avg_CPU_Time
FROM sys.dm_exec_cached_plans cp
INNER JOIN sys.dm_exec_query_stats qs
ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
WHERE DB_NAME(st.dbid) IS NOT NULL
GROUP BY DB_NAME(st.dbid),OBJECT_SCHEMA_NAME(objectid,st.dbid),cp.objtype,OBJECT_NAME(objectid,st.dbid)
ORDER BY sum(qs.total_worker_time) desc