web-dev-qa-db-ja.com

Glenn Berryクエリの疑問(データベースあたりのCPU)

このような質問を投稿する場所でない場合は、お知らせください。削除します。

Glenn berryの Diagnosticクエリ の内部には、データベースが使用しているCPUの量を示すクエリがあります。これはクエリです:

-- Get CPU utilization by database (Query 24) (CPU Usage by Database)
WITH DB_CPU_Stats
AS
(SELECT DatabaseID,
        DB_Name(DatabaseID) AS [Database Name],
        SUM(total_worker_time) AS [CPU_Time_Ms]
 FROM sys.dm_exec_query_stats AS qs
 CROSS APPLY (SELECT CONVERT(int, value) AS [DatabaseID] 
              FROM sys.dm_exec_plan_attributes(qs.plan_handle)
             WHERE attribute = N'dbid'
              ) AS F_DB
 GROUP BY DatabaseID)
SELECT ROW_NUMBER() OVER(ORDER BY [CPU_Time_Ms] DESC) AS [CPU Rank],
       [Database Name], [CPU_Time_Ms] AS [CPU Time (ms)], 
       CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPU Percent]
FROM DB_CPU_Stats
WHERE DatabaseID <> 32767 -- ResourceDB 
ORDER BY [CPU Rank] OPTION (RECOMPILE);

そして、私が知りたいのは、これがnowがより多くのCPUを使用しているデータベースを表示するクエリであるか、または過去の情報に基づいていますか?

サーバーのCPU使用率が高くなっている原因を調べようとしています。

enter image description here

この図ではサーバーはかなり良いですが、ほとんどの場合、CPU使用率が90%以上あり、sp_whoisactive何も見つけることができません(明らかに多くのクエリを取得しましたが、それらのどれもがサーバーに影響を与えているようには見えません)。そして、それは私が理解するのに問題を抱えているものです。低読み取り/書き込みサーバーがどのように多くのCPUを使用しているのでしょうか。 I/OにはCPUとの共通点はありませんか?

私はそれを移行するために、どのデータベースが最も重いのかを知りたいと思っています。

6
Racer SQL

一見すると、これはsys.dm_exec_query_statsの履歴(通常は最後の再起動以降)に基づいて、データベースあたりのCPUを概算するように見えますが、現在キャッシュ内にあるプランについてのみです。また、プランキャッシュ属性dbidにも依存します。これは、クエリのコンテキストであったことを意味しますが、作業を引き起こしたデータベースであるとは限りません。たとえば、このクエリですべてのCPUが報告される場所を推測します。

USE tempdb;
GO
SELECT CONVERT(DATETIME, CONVERT(CHAR(10), CONVERT(DATE, 
  CONVERT(DATETIME, o.create_date)), 120))
FROM msdb.sys.all_objects AS o
CROSS APPLY model.sys.all_columns AS c;

ヒントを差し上げます:msdbmodelではありません。

したがって、それは球場として使用する必要がありますが、100%現実の100%を反映するという保証はありません。クエリを頻繁に実行する(たとえば、n分ごとにそのスナップショットを保存する自動ジョブがある)と、より正確になりますが、各データベースを侵入不可能なサイロのように扱うアプリケーションがない限り、データベースコンテキストの影響を受けますクエリとデータの実際のソースではなく。

6
Aaron Bertrand

sys.dm_exec_query_statsは、SQL Serverで キャッシュされたクエリプランの集計パフォーマンス統計 を返します。プランがキャッシュから削除されると、対応する行がこのビューから削除されます。

ここでの含意は、この動的管理ビューが要件を部分的にのみ満たすことです。アーロンが彼の回答で述べたように、特定のデータベースへの帰属はクエリのコンテキストに敏感です。また、プランがあまり長くキャッシュされていない場合、このクエリを実行するときにプランがキャッシュにない可能性があるため、レポートされません。システムが動的クエリを実行している場合、プランキャッシュに使い捨てプランが殺到している可能性があり、それがこのパフォーマンスメトリックの信頼性を大幅に制限している可能性があります。

「アドホックワークロードの最適化」がオンになっていますか?次のクエリで確認します。

SELECT c.name 
    , c.value_in_use
FROM sys.configurations c
WHERE c.name = 'optimize for ad hoc workloads';

次のクエリを使用して、プランキャッシュが時間の経過とともにどのように変化しているかを確認できます。

BEGIN TRY
CREATE TABLE #PC1
(
    refcounts INT
    , usecounts INT
    , size_in_bytes INT
    , memory_object_address varbinary(32)
    , cacheobjtype VARCHAR(255)
    , objtype VARCHAR(255)
    , plan_handle VARBINARY(32)
    , [dbid] INT
    , objectid INT
    , query_plan XML
);
END TRY
BEGIN CATCH
END CATCH
BEGIN TRY
CREATE TABLE #PC2
(
    refcounts INT
    , usecounts INT
    , size_in_bytes INT
    , memory_object_address varbinary(32)
    , cacheobjtype VARCHAR(255)
    , objtype VARCHAR(255)
    , plan_handle VARBINARY(32)
    , [dbid] INT
    , objectid INT
    , query_plan XML
);
END TRY
BEGIN CATCH
END CATCH

TRUNCATE TABLE #PC1;
TRUNCATE TABLE #PC2;

INSERT INTO #PC1
(
    refcounts 
    , usecounts 
    , size_in_bytes 
    , memory_object_address 
    , cacheobjtype 
    , objtype 
    , plan_handle 
    , [dbid] 
    , objectid 
    , query_plan 
)
SELECT 
    refcounts 
    , usecounts 
    , size_in_bytes 
    , memory_object_address 
    , cacheobjtype 
    , objtype 
    , plan_handle 
    , [dbid] 
    , objectid 
    , query_plan 
FROM sys.dm_exec_cached_plans decp
    CROSS APPLY sys.dm_exec_query_plan(decp.plan_handle) t
ORDER BY decp.usecounts DESC;

WAITFOR DELAY '00:01:00';

INSERT INTO #PC2
(
    refcounts 
    , usecounts 
    , size_in_bytes 
    , memory_object_address 
    , cacheobjtype 
    , objtype 
    , plan_handle 
    , [dbid] 
    , objectid 
    , query_plan 
)
SELECT 
    refcounts 
    , usecounts 
    , size_in_bytes 
    , memory_object_address 
    , cacheobjtype 
    , objtype 
    , plan_handle 
    , [dbid] 
    , objectid 
    , query_plan 
FROM sys.dm_exec_cached_plans decp
    CROSS APPLY sys.dm_exec_query_plan(decp.plan_handle) t
ORDER BY decp.usecounts DESC;

SELECT QueryPlan = pc1.query_plan
    , UseCount = pc2.usecounts - pc1.usecounts
    , PlanSize = pc1.size_in_bytes
    , CacheType = pc1.cacheobjtype
    , objType = pc1.objtype
    , DatabaseID = pc1.dbid
FROM #PC1 pc1
    INNER JOIN #PC2 pc2 ON pc1.plan_handle = pc2.plan_handle
WHERE pc2.usecounts - pc1.usecounts > 0
ORDER BY (pc2.usecounts - pc1.usecounts);

SELECT QueryPlan = pc1.query_plan
    , UseCount = pc1.usecounts
    , PlanSize = pc1.size_in_bytes
    , CacheType = pc1.cacheobjtype
    , objType = pc1.objtype
    , DatabaseID = pc1.dbid
FROM #PC1 pc1
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM #PC2 pc2 
    WHERE pc2.plan_handle = pc1.plan_handle
)
ORDER BY (pc1.usecounts);

SELECT QueryPlan = pc2.query_plan
    , UseCount = pc2.usecounts
    , PlanSize = pc2.size_in_bytes
    , CacheType = pc2.cacheobjtype
    , objType = pc2.objtype
    , DatabaseID = pc2.dbid
FROM #PC2 pc2
WHERE NOT EXISTS 
(
    SELECT 1 
    FROM #PC1 pc1 
    WHERE pc1.plan_handle = pc2.plan_handle
)
ORDER BY (pc2.usecounts);

このクエリはプランキャッシュを2回調べ、その間に1分間待機します。次に、3つの結果セットを返します。

  • 1つ目は、1回目と2回目の実行の間にキャッシュに残った計画を示しています。 (持続計画)
  • 2番目は、最初の実行中にキャッシュにあったが、2番目の実行中にはもはやキャッシュになかったプランを示しています。 (立ち退き計画)
  • 3番目は、2回目の実行中にキャッシュにあったが、最初の実行ではなかった計画を示しています。 (新計画)

最初の結果セットが2番目の結果セットよりもはるかに少ないプランの数を示している場合は、サーバーのキャッシュ領域が絶えず不足していることを示しています。これは明らかに、Glennのクエリが期待するほど信頼できるものではないことを示しています。

5
Max Vernon