Sementara saya, seperti @Thomas, sepenuhnya setuju dengan @ Harun dalam komentar tentang pertanyaan tentang "penggunaan CPU per-basis data" menjadi akurat atau berguna, saya setidaknya bisa menjawab pertanyaan mengapa kedua pertanyaan itu sangat berbeda. Dan alasan mengapa mereka berbeda akan menunjukkan mana yang lebih akurat, meskipun tingkat akurasi yang lebih tinggi masih relatif terhadap yang secara spesifik tidak akurat, karenanya masih belum benar-benar akurat ;-).
Kueri pertama menggunakan sys.dm_exec_query_stats untuk mendapatkan info CPU (yaitu total_worker_time
). Jika Anda pergi ke halaman tertaut yang merupakan dokumentasi MSDN untuk DMV itu, Anda akan melihat intro pendek 3 kalimat dan 2 kalimat tersebut memberi kita sebagian besar dari apa yang perlu kita pahami konteks info ini ("seberapa andal itu" dan "bagaimana perbandingannya dengan sys.sysprocesses
"). Dua kalimat itu adalah:
Mengembalikan statistik kinerja gabungan untuk paket kueri yang di-cache di SQL Server. ... Ketika sebuah rencana dihapus dari cache, baris yang sesuai dihilangkan dari pandangan ini
Kalimat pertama, "Pengembalian statistik kinerja agregat ", memberi tahu kami bahwa informasi dalam DMV ini (seperti beberapa yang lain) bersifat kumulatif dan tidak khusus untuk hanya kueri yang sedang berjalan. Ini juga ditunjukkan oleh bidang dalam DMV yang bukan bagian dari kueri dalam Pertanyaan execution_count
, yang lagi-lagi menunjukkan bahwa ini adalah data kumulatif. Dan sangat berguna untuk membuat data ini menjadi kumulatif karena Anda bisa mendapatkan rata-rata, dll dengan membagi beberapa metrik dengan execution_count
.
Kalimat kedua, "paket yang dihapus dari cache juga dihapus dari DMV ini", menunjukkan bahwa itu bukan gambar yang lengkap sama sekali, terutama jika server sudah memiliki cache paket yang cukup lengkap dan sedang dimuat dan karenanya paket yang kedaluwarsa agak sering. Juga, sebagian besar DMV di-reset ketika server me-reset sehingga mereka bukan sejarah yang sebenarnya bahkan jika baris ini tidak dihapus ketika paket berakhir.
Sekarang mari kita kontraskan di atas dengan sys.sysprocesses
. Tampilan sistem ini hanya menampilkan apa yang sedang berjalan, seperti kombinasi sys.dm_exec_connections , sys.dm_exec_sessions , dan sys.dm_exec_requests (yang dinyatakan pada halaman yang terhubung untuk sys.dm_exec_sessions
). Ini adalah pandangan yang sama sekali berbeda dari server dibandingkan dengan sys.dm_exec_query_stats
DMV yang menyimpan data bahkan setelah proses selesai. Artinya, terkait dengan "apakah hasil dari kueri kedua salah?" pertanyaan, mereka tidak salah, mereka hanya berkaitan dengan aspek yang berbeda (yaitu kerangka waktu) dari statistik kinerja.
Jadi, permintaan menggunakan sys.sysprocesses
hanya melihat "sekarang". Dan query menggunakan sys.dm_exec_query_stats
adalah melihat sebagian besar (mungkin) apa yang telah terjadi sejak terakhir restart layanan SQL Server (atau jelas sistem reboot). Untuk analisis kinerja umum, tampaknya itu sys.dm_exec_query_stats
jauh lebih baik, tetapi sekali lagi, ia menjatuhkan informasi yang bermanfaat setiap saat. Dan, dalam kedua kasus, Anda juga perlu mempertimbangkan poin yang dibuat oleh @ Harun dalam komentar pertanyaan (sejak dihapus) mengenai keakuratan nilai "database_id" di tempat pertama (yaitu hanya mencerminkan DB aktif yang memprakarsai kode , belum tentu di mana "masalah" terjadi).
Tapi, jika Anda hanya perlu / ingin mendapatkan rasa apa yang terjadi sekarang di semua Database, mungkin karena hal-hal yang melambat sekarang, Anda lebih baik menggunakan kombinasi dari sys.dm_exec_connections
, sys.dm_exec_sessions
, dan sys.dm_exec_requests
(dan bukan usang sys.sysprocesses
). Perlu diingat bahwa Anda melihat / untuk permintaan , bukan basis data , karena permintaan dapat bergabung di banyak basis data, termasuk UDF dari satu atau lebih basis data, dll.
EDIT:
Jika kekhawatiran keseluruhan adalah mengurangi konsumen CPU yang tinggi, maka cari pertanyaan yang mengambil paling banyak CPU, karena database tidak benar-benar mengambil CPU (mencari per database mungkin bekerja di perusahaan hosting di mana setiap database terisolasi dan dimiliki oleh pelanggan yang berbeda).
Kueri berikut akan membantu mengidentifikasi kueri dengan penggunaan CPU rata-rata tinggi. Itu mengembun data dalam DM_ query_stats karena catatan tersebut dapat menampilkan kueri yang sama (ya, bagian yang sama dari kumpulan kueri) beberapa kali, masing-masing dengan rencana eksekusi yang berbeda.
;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
dalam milidetik?