Belirli bir örnek için veritabanına göre CPU kullanımı nasıl alınır?


15

CPU kullanımını veritabanı ile tespit etmek için aşağıdaki sorguları buldum, ancak farklı sonuçlar gösteriyorlar:

WITH DB_CPU_Stats
AS
(
    SELECT DatabaseID, DB_Name(DatabaseID) AS [DatabaseName], 
      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 [row_num],
       DatabaseName,
        [CPU_Time_Ms], 
       CAST([CPU_Time_Ms] * 1.0 / SUM([CPU_Time_Ms]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPUPercent]
FROM DB_CPU_Stats
--WHERE DatabaseID > 4 -- system databases
--AND DatabaseID <> 32767 -- ResourceDB
ORDER BY row_num OPTION (RECOMPILE);

Yukarıdaki sorgu, sorunun veritabanımdan birinde (neredeyse% 96) olduğunu söylüyor.

Ve aşağıdaki sorgu, sorunun ana ve dağıtım veritabanlarıyla (yaklaşık% 90) ilgili olduğunu söyler:

DECLARE @total INT
SELECT @total=sum(cpu) FROM sys.sysprocesses sp (NOLOCK)
    join sys.sysdatabases sb (NOLOCK) ON sp.dbid = sb.dbid

SELECT sb.name 'database', @total 'system cpu', SUM(cpu) 'database cpu', CONVERT(DECIMAL(4,1), CONVERT(DECIMAL(17,2),SUM(cpu)) / CONVERT(DECIMAL(17,2),@total)*100) '%'
FROM sys.sysprocesses sp (NOLOCK)
JOIN sys.sysdatabases sb (NOLOCK) ON sp.dbid = sb.dbid
--WHERE sp.status = 'runnable'
GROUP BY sb.name
ORDER BY CONVERT(DECIMAL(4,1), CONVERT(DECIMAL(17,2),SUM(cpu)) / CONVERT(DECIMAL(17,2),@total)*100) desc

Ben sys.sysprocessesçözülmüş olduğunu kontrol ettim. Bu, ikinci sorgudan elde edilen sonuçların yanlış olduğu anlamına mı geliyor?

Yanıtlar:


14

@Thomas gibi, "veritabanı başına CPU kullanımı" ya doğru ya da yararlı olma endişeleri hakkındaki sorudaki yorumlarda @Aaron ile tamamen aynı fikirdeyken, en azından bu iki sorgunun neden bu kadar olduğu sorusuna cevap verebilirim. farklı. Ve farklı olmalarının nedeni hangisinin daha doğru olduğunu gösterecektir, ancak daha yüksek doğruluk seviyesi hala yanlış olanla göreceli olarak hala doğru değildir ;-).

İlk sorgu CPU bilgilerini almak için sys.dm_exec_query_stats kullanır total_worker_time. Bu DMV için MSDN dokümantasyonu olan bağlantılı sayfaya giderseniz, kısa, 3 cümle girişi ve bu cümlelerin 2'si bize bu bilgilerin içeriğini anlamak için ihtiyaç duyduğumuz şeylerin çoğunu verir ("ne kadar güvenilir") ve "nasıl karşılaştırılır sys.sysprocesses"). Bu iki cümle:

SQL Server'da önbelleğe alınmış sorgu planları için toplam performans istatistiklerini döndürür. ... Bir plan önbellekten kaldırıldığında, karşılık gelen satırlar bu görünümden kaldırılır

İlk cümle olan " Toplam performans istatistiklerini döndürür ", bize bu DMV'deki (tıpkı diğerleri gibi) bilgilerin birikimli olduğunu ve yalnızca şu anda çalışan sorgulara özgü olmadığını belirtir. Bu aynı zamanda, DMV'deki Sorunun sorgusunun bir parçası olmayan execution_countve yine bunun birikimli veriler olduğunu gösteren bir alanla belirtilir . Ve metriklerin bazılarını bölerek ortalamalar vb. Alabileceğiniz gibi bu verilerin birikimli olması oldukça kullanışlıdır execution_count.

İkinci cümle, "önbellekten kaldırılan planlar da bu DMV'den kaldırılır", özellikle sunucunun zaten tam bir tam önbelleğe sahip olması ve yük altında olması ve bu nedenle planların süresinin dolması durumunda, tam bir resim olmadığını gösterir. biraz sık. Ayrıca, çoğu DMV sunucu sıfırlandığında sıfırlanır, böylece planlar sona erdiğinde bu satırlar kaldırılmasa bile gerçek bir geçmiş olmaz.

Şimdi yukarıdakileri kontrastla ele alalım sys.sysprocesses. Bu sistem görünümü, yalnızca sys.dm_exec_connections , sys.dm_exec_sessions ve sys.dm_exec_requests (bağlı sayfada belirtilen) kombinasyonu gibi, şu anda çalışmakta olanları gösterir sys.dm_exec_sessions. Bu, sys.dm_exec_query_statsişlem tamamlandıktan sonra bile verileri tutan DMV ile karşılaştırıldığında sunucunun tamamen farklı bir görünümüdür . Anlamı, "ikinci sorgudan elde edilen sonuçlar yanlış mı?" soru, onlar yanlış değil, sadece performans istatistiklerinin farklı bir yönü (yani zaman çerçevesi) ile ilgilidir.

Yani, kullanarak sorgu sys.sysprocessessadece "şu anda" bakıyor. Ve kullanarak sorgu çoğunlukla (belki) SQL Server hizmetinin son yeniden başlatılmasından bu yana neler olduğunu (veya açıkçası sistem yeniden başlatma) sys.dm_exec_query_statsbakıyor . Genel performans analizi için çok daha iyi olduğu görülüyor , ancak yine de yararlı bilgiler her zaman düşüyor. Ve her iki durumda da, ilk başta "database_id" değerinin doğruluğuna ilişkin soru yorumlarında (kaldırıldığından beri) @Aaron tarafından yapılan noktaları dikkate almanız gerekir (yani, yalnızca kodu başlatan etkin DB'yi yansıtır. , "sorunun" oluştuğu yer değildir).sys.dm_exec_query_stats

Sadece ihtiyacın olursa, / şimdilik işler yolunda yavaşlıyorlar muhtemelen, çünkü kombinasyonunu kullanarak daha iyi, tüm Veritabanları genelinde şu anda olup bitenlerin bir fikir edinmek istiyorum sys.dm_exec_connections, sys.dm_exec_sessionsve sys.dm_exec_requests(değil kaldırılan sys.sysprocesses). Veritabanlarına değil sorgulara baktığınızı unutmayın , çünkü sorgular birden çok veritabanına katılabilir, bir veya daha fazla veritabanından UDF'ler vb.


DÜZENLEME:
Genel endişe yüksek CPU tüketicilerini azaltmak ise, en çok CPU alan sorguları arayın, çünkü veritabanları aslında CPU'yu üstlenmez (veritabanına bakmak her veritabanının izole edildiği bir barındırma şirketinde çalışabilir ve farklı bir müşteriye ait).

Aşağıdaki sorgu, yüksek ortalama CPU kullanımı olan sorguların belirlenmesine yardımcı olacaktır. Bu kayıtlar, her biri farklı bir yürütme planına sahip olan aynı sorguyu (evet, sorgu grubunun aynı alt kümesini) birden çok kez gösterebildiğinden, sorgu_statları DMV'sindeki verileri yoğunlaştırır.

;WITH cte AS
(
  SELECT stat.[sql_handle],
         stat.statement_start_offset,
         stat.statement_end_offset,
         COUNT(*) AS [NumExecutionPlans],
         SUM(stat.execution_count) AS [TotalExecutions],
         ((SUM(stat.total_logical_reads) * 1.0) / SUM(stat.execution_count)) AS [AvgLogicalReads],
         ((SUM(stat.total_worker_time) * 1.0) / SUM(stat.execution_count)) AS [AvgCPU]
  FROM sys.dm_exec_query_stats stat
  GROUP BY stat.[sql_handle], stat.statement_start_offset, stat.statement_end_offset
)
SELECT CONVERT(DECIMAL(15, 5), cte.AvgCPU) AS [AvgCPU],
       CONVERT(DECIMAL(15, 5), cte.AvgLogicalReads) AS [AvgLogicalReads],
       cte.NumExecutionPlans,
       cte.TotalExecutions,
       DB_NAME(txt.[dbid]) AS [DatabaseName],
       OBJECT_NAME(txt.objectid, txt.[dbid]) AS [ObjectName],
       SUBSTRING(txt.[text], (cte.statement_start_offset / 2) + 1,
       (
         (CASE cte.statement_end_offset 
           WHEN -1 THEN DATALENGTH(txt.[text])
           ELSE cte.statement_end_offset
          END - cte.statement_start_offset) / 2
         ) + 1
       )
FROM cte
CROSS APPLY sys.dm_exec_sql_text(cte.[sql_handle]) txt
ORDER BY cte.AvgCPU DESC;

olduğu AvgCPUmilisaniye cinsinden?
Kolob Kanyonu

Merhaba @KolobCanyon. Belgelerine göre sys.dm_exec_query_stats , total_worker_time"dır o derlendi beri bu planın infaz tarafından tüketildiği mikrosaniye (ama milisaniye yegane hassas) bildirilen CPU zamanı toplam tutarı,. ". Bu yardımcı olur mu? Görmek istediğiniz şey buysa, kolayca milisaniyeye dönüştürülebilir.
Solomon Rutzky

1

Sorgulamayı 0 hataya bölme ve Excel'e kopyala / yapıştır için optimize edilmiş sütun adları ayarladım.

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
GO
WITH DB_CPU_Stats
AS
(
    SELECT DatabaseID, isnull(DB_Name(DatabaseID),case DatabaseID when 32767 then 'Internal ResourceDB' else CONVERT(varchar(255),DatabaseID)end) AS [DatabaseName], 
      SUM(total_worker_time) AS [CPU_Time_Ms],
      SUM(total_logical_reads)  AS [Logical_Reads],
      SUM(total_logical_writes)  AS [Logical_Writes],
      SUM(total_logical_reads+total_logical_writes)  AS [Logical_IO],
      SUM(total_physical_reads)  AS [Physical_Reads],
      SUM(total_elapsed_time)  AS [Duration_MicroSec],
      SUM(total_clr_time)  AS [CLR_Time_MicroSec],
      SUM(total_rows)  AS [Rows_Returned],
      SUM(execution_count)  AS [Execution_Count],
      count(*) 'Plan_Count'
    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 [Rank_CPU],
       DatabaseName,
       [CPU_Time_Hr] = convert(decimal(15,2),([CPU_Time_Ms]/1000.0)/3600) ,
        CAST([CPU_Time_Ms] * 1.0 / SUM(case [CPU_Time_Ms] when 0 then 1 else [CPU_Time_Ms] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPU_Percent],
       [Duration_Hr] = convert(decimal(15,2),([Duration_MicroSec]/1000000.0)/3600) , 
       CAST([Duration_MicroSec] * 1.0 / SUM(case [Duration_MicroSec] when 0 then 1 else [Duration_MicroSec] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Duration_Percent],    
       [Logical_Reads],
        CAST([Logical_Reads] * 1.0 / SUM(case [Logical_Reads] when 0 then 1 else [Logical_Reads] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Logical_Reads_Percent],      
       [Rows_Returned],
        CAST([Rows_Returned] * 1.0 / SUM(case [Rows_Returned] when 0 then 1 else [Rows_Returned] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Rows_Returned_Percent],
       [Reads_Per_Row_Returned] = [Logical_Reads]/(case [Rows_Returned] when 0 then 1 else [Rows_Returned] end),
       [Execution_Count],
        CAST([Execution_Count] * 1.0 / SUM(case [Execution_Count]  when 0 then 1 else [Execution_Count] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Execution_Count_Percent],
       [Physical_Reads],
       CAST([Physical_Reads] * 1.0 / SUM(case [Physical_Reads] when 0 then 1 else [Physical_Reads] end ) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Physcal_Reads_Percent], 
       [Logical_Writes],
        CAST([Logical_Writes] * 1.0 / SUM(case [Logical_Writes] when 0 then 1 else [Logical_Writes] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Logical_Writes_Percent],
       [Logical_IO],
        CAST([Logical_IO] * 1.0 / SUM(case [Logical_IO] when 0 then 1 else [Logical_IO] end) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Logical_IO_Percent],
       [CLR_Time_MicroSec],
       CAST([CLR_Time_MicroSec] * 1.0 / SUM(case [CLR_Time_MicroSec] when 0 then 1 else [CLR_Time_MicroSec] end ) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CLR_Time_Percent],
       [CPU_Time_Ms],[CPU_Time_Ms]/1000 [CPU_Time_Sec],
       [Duration_MicroSec],[Duration_MicroSec]/1000000 [Duration_Sec]
FROM DB_CPU_Stats
WHERE DatabaseID > 4 -- system databases
AND DatabaseID <> 32767 -- ResourceDB
ORDER BY [Rank_CPU] OPTION (RECOMPILE);

0

CPU sorgusunu sys.dm_exec_query_statso kadar çok sevdim ki uzattım . Hala CPU tarafından derecelendirildi, ancak daha iyi bir sunucu profili elde etmek için diğer toplamları ve yüzdeleri ekledim. Bu, Excel'e güzel bir şekilde kopyalanır ve Yüzde sütunlarında koşullu renk biçimlendirmesiyle, en kötü sayılar güzelleşir. 'Dereceli Renk Skalası'nı 3 renkle kullandım; yüksek değerler için bir gül rengi, orta için sarı, düşük için yeşil.

database id 32676Dahili SQL Kaynak Veritabanı olan bir Etiket ekledim . Daha iyi bir zaman kullanımı hissi elde etmek için CPU ve Süre zamanını Saat'e çeviriyorum.

WITH DB_CPU_Stats
AS
(
    SELECT DatabaseID, isnull(DB_Name(DatabaseID),case DatabaseID when 32767 then 'Internal ResourceDB' else CONVERT(varchar(255),DatabaseID)end) AS [DatabaseName], 
      SUM(total_worker_time) AS [CPU Time Ms],
      SUM(total_logical_reads)  AS [Logical Reads],
      SUM(total_logical_writes)  AS [Logical Writes],
      SUM(total_logical_reads+total_logical_writes)  AS [Logical IO],
      SUM(total_physical_reads)  AS [Physical Reads],
      SUM(total_elapsed_time)  AS [Duration MicroSec],
      SUM(total_clr_time)  AS [CLR Time MicroSec],
      SUM(total_rows)  AS [Rows Returned],
      SUM(execution_count)  AS [Execution Count],
      count(*) 'Plan Count'

    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 [Rank CPU],
       DatabaseName,
       [CPU Time Hr] = convert(decimal(15,2),([CPU Time Ms]/1000.0)/3600) ,
        CAST([CPU Time Ms] * 1.0 / SUM([CPU Time Ms]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CPU Percent],
       [Duration Hr] = convert(decimal(15,2),([Duration MicroSec]/1000000.0)/3600) , 
       CAST([Duration MicroSec] * 1.0 / SUM([Duration MicroSec]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Duration Percent],    
       [Logical Reads],
        CAST([Logical Reads] * 1.0 / SUM([Logical Reads]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Logical Reads Percent],      
       [Rows Returned],
        CAST([Rows Returned] * 1.0 / SUM([Rows Returned]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Rows Returned Percent],
       [Reads Per Row Returned] = [Logical Reads]/[Rows Returned],
       [Execution Count],
        CAST([Execution Count] * 1.0 / SUM([Execution Count]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Execution Count Percent],
       [Physical Reads],
       CAST([Physical Reads] * 1.0 / SUM([Physical Reads]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Physcal Reads Percent], 
       [Logical Writes],
        CAST([Logical Writes] * 1.0 / SUM([Logical Writes]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Logical Writes Percent],
       [Logical IO],
        CAST([Logical IO] * 1.0 / SUM([Logical IO]) OVER() * 100.0 AS DECIMAL(5, 2)) AS [Logical IO Percent],
       [CLR Time MicroSec],
       CAST([CLR Time MicroSec] * 1.0 / SUM(case [CLR Time MicroSec] when 0 then 1 else [CLR Time MicroSec] end ) OVER() * 100.0 AS DECIMAL(5, 2)) AS [CLR Time Percent],
       [CPU Time Ms],[CPU Time Ms]/1000 [CPU Time Sec],
       [Duration MicroSec],[Duration MicroSec]/1000000 [Duration Sec]
FROM DB_CPU_Stats
--WHERE DatabaseID > 4 -- system databases
--AND DatabaseID <> 32767 -- ResourceDB
ORDER BY [Rank CPU] OPTION (RECOMPILE);
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.