Si bien, al igual que @Thomas, estoy completamente de acuerdo con @Aaron en los comentarios sobre la pregunta sobre si el uso de CPU por base de datos es preciso o útil, al menos puedo responder a la pregunta de por qué esas dos consultas son tan diferente. Y la razón por la cual son diferentes indicará cuál es más preciso, aunque ese mayor nivel de precisión sigue siendo relativo al que es específicamente inexacto, por lo tanto, aún no es realmente preciso ;-).
La primera consulta usa sys.dm_exec_query_stats para obtener información de la CPU (es decir total_worker_time
). Si va a la página vinculada que es la documentación de MSDN para ese DMV, verá una breve introducción de 3 oraciones y 2 de esas oraciones nos dan la mayor parte de lo que necesitamos para comprender el contexto de esta información ("cuán confiable es" y "cómo se compara con sys.sysprocesses
"). Esas dos oraciones son:
Devuelve estadísticas de rendimiento agregado para planes de consulta en caché en SQL Server. ... Cuando se elimina un plan de la memoria caché, las filas correspondientes se eliminan de esta vista
La primera oración, "Devuelve estadísticas de rendimiento agregado ", nos dice que la información en este DMV (al igual que muchas otras) es acumulativa y no específica para solo las consultas que se están ejecutando actualmente. Esto también se indica mediante un campo en ese DMV que no forma parte de la consulta en la Pregunta execution_count
, que nuevamente muestra que se trata de datos acumulativos. Y es bastante útil que estos datos sean acumulativos, ya que puede obtener promedios, etc., dividiendo algunas de las métricas por execution_count
.
La segunda oración, "los planes que se eliminan del caché también se eliminan de este DMV", indican que no es una imagen completa en absoluto, especialmente si el servidor ya tiene un caché de plan bastante completo y está bajo carga y, por lo tanto, está caducando los planes algo frecuente Además, la mayoría de los DMV se restablecen cuando el servidor se reinicia, por lo que no son un historial real, incluso si estas filas no se eliminaron cuando caducan los planes.
Ahora vamos a contrastar lo anterior con sys.sysprocesses
. Esta vista del sistema solo muestra lo que se está ejecutando actualmente, al igual que la combinación de sys.dm_exec_connections , sys.dm_exec_sessions y sys.dm_exec_requests (que se indica en la página vinculada para sys.dm_exec_sessions
). Esta es una vista completamente diferente del servidor en comparación con el sys.dm_exec_query_stats
DMV que contiene los datos incluso después de que se complete el proceso. Es decir, en relación con "¿son incorrectos los resultados de la segunda consulta?" pregunta, no están equivocados, solo pertenecen a un aspecto diferente (es decir, el marco temporal) de las estadísticas de rendimiento.
Entonces, la consulta que usa sys.sysprocesses
solo está mirando "en este momento". Y la consulta que usa sys.dm_exec_query_stats
está mirando principalmente (tal vez) lo que ha sucedido desde el último reinicio del servicio SQL Server (o obviamente reinicio del sistema). Para el análisis de rendimiento general parece que sys.dm_exec_query_stats
es mucho mejor, pero nuevamente, deja caer información útil todo el tiempo. Y, en ambos casos, también debe considerar los puntos hechos por @Aaron en los comentarios de la pregunta (ya eliminados) con respecto a la precisión del valor "database_id" en primer lugar (es decir, solo refleja la base de datos activa que inició el código) , no necesariamente donde está ocurriendo el "problema").
Pero, si lo que necesita / quiere tener una idea de lo que está sucediendo ahora mismo en todas las bases de datos, posiblemente porque las cosas se están desacelerando en este momento, es mejor usar la combinación de sys.dm_exec_connections
, sys.dm_exec_sessions
y sys.dm_exec_requests
(y no el obsoleto sys.sysprocesses
). Solo tenga en cuenta que está buscando / para consultas , no para bases de datos , porque las consultas pueden unirse a través de múltiples bases de datos, incluir UDF de una o más bases de datos, etc.
EDITAR:
si la preocupación general es reducir el consumo elevado de CPU, busque las consultas que ocupan más CPU, porque las bases de datos en realidad no ocupan CPU (la búsqueda por base de datos podría funcionar en una empresa de alojamiento donde cada base de datos está aislada y propiedad de un cliente diferente).
La siguiente consulta ayudará a identificar consultas con un uso de CPU promedio alto. Condensa los datos en el DMV query_stats ya que esos registros pueden mostrar la misma consulta (sí, el mismo subconjunto del lote de consulta) varias veces, cada una con un plan de ejecución diferente.
;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
en milisegundos?