2008-08-26 6 views
29

データベースでCPU使用率の内訳を取得できますか?データベースによるCPU使用率ですか?

私は理想的にはSQLサーバ用のタスクマネージャタイプのインターフェイスを探していますが、各PID(taskmgrなど)や各SPID(spwho2k5など)のCPU使用率を調べるのではなく、各データベースの単一のSQLインスタンスを想定します。

このデータを収集して報告するためのツールが書かれていることがわかりましたが、sqlservr.exe CPU負荷にどのデータベースが最も寄与しているかをライブビューで確認できるツールがあれば疑問です。

答えて

81

並べ替えこのクエリを確認してください:

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では、しかし、個々のデータベースをバックアップします。

それは繰り返します。そのため、データベースレベルではなくクエリレベルでのパフォーマンスの調整が理にかなっています。

マイクロソフトでは、パフォーマンス管理とアプリケーション管理機能を導入して、1つのデータベースを配布可能で展開可能なDACパックにパッケージ化することができました。また、個々のデータベースのパフォーマンス管理を容易にする有望な機能ですそれらのアプリケーション。しかし、あなたが探しているものはまだやっていません。

さらに詳しくは、T-SQL repository at Toad World's SQL Server wiki (formerly at SQLServerPedia)をご覧ください。

1/29に更新され、平均値ではなく合計数値が追加されました。

+1

私の無知ですが、AvgCPUとAvgDurationの単位は何ですか? – Portman

+1

CPU時間とミリ秒の両方のミリ秒単位のミリ秒。 IO、ロック、クライアントなどでクエリを待つことができるため、これらは異なる可能性があります。私は合計を取得するようにクエリを変更します。 (私はフットポンドを言うつもりでしたが、私は仮想の真っ直ぐな顔を保つことができませんでした。) –

15

SQL Server(2000以降)では、パフォーマンスカウンタ(パフォーマンスモニタまたはパフォーマンスモニタから表示可能)がインストールされます。各データベースに1つのインスタンスを持つデータベース

:SQLServerの -

カウンターカテゴリの一つは、(SQL Serverから2005インストール:) です。ただし、利用可能なカウンタはCPU%使用率カウンタなどを提供していませんが、いくつかのレートカウンタがありますが、これを使用してCPUの推定値を取得できます。たとえば、2つのデータベースがあり、測定されたレートがデータベースAで20トランザクション/秒、データベースBで80トランス/秒である場合、Aは合計CPUのおよそ20%を占めることがわかります。 Bは他の80%に貢献します。

ここにはいくつかの欠陥があります。これは、実行されているすべての作業がCPUにバインドされていることを前提としています。しかし、それは私が信じるスタートになるでしょう。

1

あなたの質問に対する答えはノーだと思います。

マシン上の1つのアクティビティが複数のデータベースに負荷を与える可能性があるという問題があります。設定DBからの読み込み、ロギングDBへのロギング、タイプに基づいてさまざまなDBの内外へのトランザクションの移動を行うプロセスがある場合、どのようにCPU使用率を分割するのですか?

CPU使用率をトランザクション負荷で割ることもできますが、それは誤解を招くような大まかなメトリックです。たとえば、トランザクションログの出荷を1つのDBから別のDBに分割する方法はありますか? CPU負荷が読み書き中ですか?

マシンのトランザクションレートとそれが原因で発生するCPU負荷を確認する方がよいでしょう。また、ストアドプロシージャをプロファイリングし、いずれかが過度の時間を取っているかどうかを確認することもできます。しかし、これはあなたが望む答えを得ることはありません。

0

SQL Sentryをご覧ください。それはあなたが必要とするものすべてを行います。

よろしく、 リーフェン

0

あなたはSQLプロファイラで見たことがありますか?

標準の「T-SQL」または「ストアドプロシージャ」テンプレートを使用して、データベースIDでグループ化するフィールドを調整します(数字を使用する必要があると思いますが、データベース名は取得しませんが、 exec sp_databasesを使用してリストを取得する)

これをしばらく実行すると、合計CPU数/ディスクIO /待機時間などが表示されます。これにより、各データベースで使用されるCPUの割合がわかります。

PerfMonカウンタを同時に監視して(SQLデータベースにデータをログする)、SQLプロファイラ(データベースへのログ)に対して同じ処理を行う場合は、が2つを相互に関連付けることができます。

それでも、どのDBがより詳細に調べる価値があるかについての手がかりは十分にあるはずです。その後、そのデータベースIDだけで同じことをやり直し、最も高価なSQL /ストアドプロシージャを探します。

6

ここでは、負荷の高い実際のデータベースが表示されます。これは、低メモリシナリオで頻繁にフラッシュされる可能性のあるクエリキャッシュに依存しているため、クエリの有用性は低くなります。

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 
0

このクエリを確認してください。

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 
1

すべての心の中で上記の言って。
SQL Server 2012以降(2008年か?)、列database_idsys.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;