Bien que, comme @Thomas, je sois entièrement d'accord avec @Aaron dans les commentaires sur la question concernant les "utilisations du processeur par base de données" qui sont soit précises soit utiles, je peux au moins répondre à la question de savoir pourquoi ces deux requêtes sont si différent. Et la raison pour laquelle ils sont différents indiquera lequel est le plus précis, bien que ce niveau de précision plus élevé soit toujours relatif à celui qui est spécifiquement inexact, donc toujours pas vraiment précis ;-).
La première requête utilise sys.dm_exec_query_stats pour obtenir les informations CPU (ie total_worker_time
). Si vous allez sur la page liée qui est la documentation MSDN pour ce DMV, vous verrez une courte introduction de 3 phrases et 2 de ces phrases nous donnent la plupart de ce dont nous avons besoin pour comprendre le contexte de cette information ("quelle est la fiabilité" et "comment se compare-t-il àsys.sysprocesses
"). Ces deux phrases sont:
Renvoie des statistiques de performances agrégées pour les plans de requête mis en cache dans SQL Server. ... Lorsqu'un plan est supprimé du cache, les lignes correspondantes sont supprimées de cette vue
La première phrase, "Renvoie des statistiques de performances agrégées ", nous indique que les informations contenues dans ce DMV (comme plusieurs autres) sont cumulatives et ne sont pas spécifiques aux seules requêtes en cours d'exécution. Cela est également indiqué par un champ dans ce DMV qui ne fait pas partie de la requête dans la question execution_count
, qui montre encore une fois qu'il s'agit de données cumulatives. Et il est assez pratique d'avoir ces données cumulatives car vous pouvez obtenir des moyennes, etc. en divisant certaines des mesures par le execution_count
.
La deuxième phrase, "les plans supprimés du cache sont également supprimés de ce DMV", indique que ce n'est pas du tout une image complète, surtout si le serveur a déjà un cache de plan assez complet et est en charge et donc expire les plans assez fréquemment. De plus, la plupart des DMV sont réinitialisés lorsque le serveur est réinitialisé, ils ne constituent donc pas un véritable historique, même si ces lignes n'ont pas été supprimées à l'expiration des plans.
Maintenant, contrastons ce qui précède avec sys.sysprocesses
. Cette vue système montre uniquement ce qui est en cours d'exécution, tout comme la combinaison de sys.dm_exec_connections , sys.dm_exec_sessions et sys.dm_exec_requests (qui est indiquée sur la page liée pour sys.dm_exec_sessions
). Il s'agit d'une vue entièrement différente du serveur par rapport à lasys.dm_exec_query_stats
DMV qui contient les données même après la fin du processus. Signification, par rapport à la "les résultats de la deuxième requête sont-ils faux?" question, ils ne se trompent pas, ils se rapportent simplement à un aspect différent (c'est-à-dire le calendrier) des statistiques de performance.
Ainsi, la requête utilisant sys.sysprocesses
ne regarde que "en ce moment". Et la requête utilisant sys.dm_exec_query_stats
regarde principalement (peut-être) ce qui s'est passé depuis le dernier redémarrage du service SQL Server (ou bien évidemment le redémarrage du système). Pour l'analyse générale des performances, il semble que sys.dm_exec_query_stats
c'est beaucoup mieux, mais encore une fois, il laisse des informations utiles tout le temps. Et, dans les deux cas, vous devez également prendre en compte les points soulevés par @Aaron dans les commentaires de la question (depuis supprimés) concernant la précision de la valeur "database_id" en premier lieu (c'est-à-dire qu'elle ne reflète que la base de données active qui a initié le code , pas nécessairement là où le «problème» se produit).
Mais, si vous avez juste besoin / voulez avoir une idée de ce qui se passe en ce moment dans toutes les bases de données, peut - être parce que les choses ralentissent maintenant, vous feriez mieux d'utiliser la combinaison sys.dm_exec_connections
, sys.dm_exec_sessions
et sys.dm_exec_requests
(et non dépréciée sys.sysprocesses
). Gardez à l'esprit que vous recherchez / pour des requêtes , pas des bases de données , car les requêtes peuvent se joindre à plusieurs bases de données, inclure des UDF provenant d'une ou plusieurs bases de données, etc.
EDIT:
Si la préoccupation globale est de réduire les consommateurs de CPU élevés, recherchez les requêtes qui prennent le plus de CPU, car les bases de données n'utilisent pas réellement de CPU (la recherche par base de données peut fonctionner dans une société d'hébergement où chaque base de données est isolée et appartenant à un autre client).
La requête suivante aidera à identifier les requêtes avec une utilisation moyenne élevée du processeur. Il condense les données dans le DMV query_stats car ces enregistrements peuvent afficher plusieurs fois la même requête (oui, le même sous-ensemble du lot de requêtes), chacune avec un plan d'exécution différent.
;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 millisecondes?