@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_count
ve 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_stats
iş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.sysprocesses
sadece "ş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_stats
bakı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_sessions
ve 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;
AvgCPU
milisaniye cinsinden?