Mentre io, come @Thomas, sono completamente d'accordo con @Aaron nei commenti sulla domanda relativa alla preoccupazione che "l'utilizzo della CPU per database" sia accurato o utile, posso almeno rispondere alla domanda sul perché queste due query sono così diverso. E il motivo per cui sono diversi indicherà quale è più preciso, anche se quel livello di accuratezza più elevato è ancora relativo a quello che è specificamente inaccurato, quindi non è ancora veramente accurato ;-).
La prima query utilizza sys.dm_exec_query_stats per ottenere informazioni sulla CPU (ad es total_worker_time
.). Se vai alla pagina collegata che è la documentazione MSDN per quel DMV vedrai una breve introduzione di 3 frasi e 2 di quelle frasi ci danno la maggior parte di ciò di cui abbiamo bisogno per capire il contesto di queste informazioni ("quanto è affidabile" e "come si confronta con sys.sysprocesses
"). Queste due frasi sono:
Restituisce statistiche aggregate sulle prestazioni per i piani di query memorizzati nella cache in SQL Server. ... Quando un piano viene rimosso dalla cache, le righe corrispondenti vengono eliminate da questa vista
La prima frase, "Restituisce statistiche aggregate sulle prestazioni", ci dice che le informazioni in questo DMV (proprio come molti altri) sono cumulative e non specifiche solo per le query attualmente in esecuzione. Ciò è anche indicato da un campo in quel DMV che non fa parte della query nella Domanda execution_count
, che mostra di nuovo che si tratta di dati cumulativi. Ed è abbastanza utile che questi dati siano cumulativi in quanto è possibile ottenere medie, ecc. Dividendo alcune delle metriche per execution_count
.
La seconda frase, "i piani che vengono rimossi dalla cache vengono rimossi anche da questo DMV", indicano che non è affatto un quadro completo, specialmente se il server ha già una cache piuttosto completa del piano ed è sotto carico e quindi sta scadendo i piani piuttosto frequentemente. Inoltre, la maggior parte dei DMV vengono reimpostati quando il server viene reimpostato, quindi non sono una cronologia vera anche se queste righe non sono state rimosse alla scadenza dei piani.
Ora confrontiamo quanto sopra con sys.sysprocesses
. Questa vista di sistema mostra solo ciò che è attualmente in esecuzione, proprio come la combinazione di sys.dm_exec_connections , sys.dm_exec_sessions e sys.dm_exec_requests (che è indicato nella pagina collegata per sys.dm_exec_sessions
). Questa è una visione completamente diversa del server rispetto al sys.dm_exec_query_stats
DMV che contiene i dati anche dopo il completamento del processo. Significato, in relazione a "i risultati della seconda query sono errati?" domanda, non si sbagliano, riguardano solo un aspetto diverso (ad es. il lasso di tempo) delle statistiche delle prestazioni.
Quindi, la query che utilizza sys.sysprocesses
sta solo guardando "adesso". E la query che utilizza sys.dm_exec_query_stats
guarda principalmente (forse) cosa è successo dall'ultimo riavvio del servizio SQL Server (o ovviamente riavvio del sistema). Per l'analisi generale delle prestazioni sembra che sys.dm_exec_query_stats
sia molto meglio, ma di nuovo, rilascia continuamente informazioni utili. E, in entrambi i casi, è necessario considerare anche i punti sollevati da @Aaron nei commenti alle domande (poiché rimossi) per quanto riguarda l'accuratezza del valore "database_id" in primo luogo (ovvero riflette solo il DB attivo che ha avviato il codice , non necessariamente dove si verifica il "problema").
Ma, se avete solo bisogno / voglia di ottenere un senso di ciò che sta accadendo in questo momento in tutti i database, forse perché le cose stanno rallentando in questo momento, si sta meglio utilizzando la combinazione di sys.dm_exec_connections
, sys.dm_exec_sessions
e sys.dm_exec_requests
(e non il deprecato sys.sysprocesses
). Tieni presente che stai cercando / per query , non per database , perché le query possono unirsi su più database, includere UDF da uno o più database, ecc.
EDIT:
se la preoccupazione generale è ridurre i consumatori di CPU elevati, cerca le query che occupano la maggior parte della CPU, perché i database non occupano effettivamente la CPU (la ricerca per database potrebbe funzionare in una società di hosting in cui ogni database è isolato e di proprietà di un altro cliente).
La query seguente aiuterà a identificare le query con un utilizzo medio elevato della CPU. Condensa i dati nel DMV query_stats poiché tali record possono mostrare più volte la stessa query (sì, lo stesso sottoinsieme del batch di query), ciascuno con un piano di esecuzione diverso.
;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
in millisecondi?