Ich stimme @Aaron wie @Thomas in den Kommentaren zu der Frage zu, ob die Bedenken hinsichtlich der "CPU-Auslastung pro Datenbank" zutreffend oder nützlich sind, kann aber zumindest die Frage beantworten, warum diese beiden Fragen so sind anders. Und der Grund, warum sie unterschiedlich sind, zeigt an, welches genauer ist, obwohl dieses höhere Maß an Genauigkeit immer noch relativ zu dem ist, das spezifisch ungenau ist und daher immer noch nicht wirklich genau ist ;-).
Die erste Abfrage verwendet sys.dm_exec_query_stats , um CPU-Informationen (dh total_worker_time
) abzurufen . Wenn Sie zu der verlinkten Seite gehen, die die MSDN-Dokumentation für dieses DMV ist, sehen Sie ein kurzes 3-Satz-Intro und 2 dieser Sätze geben uns das Meiste, was wir zum Verstehen des Kontexts dieser Informationen benötigen ("wie zuverlässig ist es"). und "wie vergleicht es sich mit sys.sysprocesses
"). Diese beiden Sätze sind:
Gibt zusammengefasste Leistungsstatistiken für zwischengespeicherte Abfragepläne in SQL Server zurück. ... Wenn ein Plan aus dem Cache entfernt wird, werden die entsprechenden Zeilen aus dieser Ansicht entfernt
Der erste Satz "Gibt aggregierte Leistungsstatistiken zurück" besagt, dass die Informationen in dieser DMV (genau wie in mehreren anderen) kumulativ sind und sich nicht nur auf aktuell ausgeführte Abfragen beziehen. Dies wird auch durch ein Feld in der DMV angezeigt, das nicht Teil der Abfrage in der Frage execution_count
ist. Dies zeigt wiederum, dass es sich um kumulative Daten handelt. Und es ist sehr praktisch, wenn diese Daten kumulativ sind, da Sie Durchschnittswerte usw. erhalten können, indem Sie einige der Metriken durch dividieren execution_count
.
Der zweite Satz, "Pläne, die aus dem Cache entfernt werden, werden auch aus dieser DMV entfernt", gibt an, dass es sich überhaupt nicht um ein vollständiges Bild handelt, insbesondere wenn der Server bereits über einen ziemlich vollen Plan-Cache verfügt und ausgelastet ist und daher Pläne ablaufen etwas häufig. Außerdem werden die meisten DMVs zurückgesetzt, wenn der Server zurückgesetzt wird, sodass sie keine echte Historie darstellen, selbst wenn diese Zeilen bei Ablauf der Pläne nicht entfernt wurden.
Vergleichen wir nun das Obige mit sys.sysprocesses
. Diese Systemansicht zeigt nur, was gerade ausgeführt wird, genau wie die Kombination aus sys.dm_exec_connections , sys.dm_exec_sessions und sys.dm_exec_requests (die auf der verknüpften Seite für angegeben ist sys.dm_exec_sessions
). Dies ist eine völlig andere Ansicht des Servers als der sys.dm_exec_query_stats
DMV, der die Daten auch nach Abschluss des Vorgangs enthält. Das heißt, in Bezug auf "sind die Ergebnisse der zweiten Abfrage falsch?" Frage, sie sind nicht falsch, sie beziehen sich nur auf einen anderen Aspekt (dh Zeitrahmen) der Leistungsstatistik.
Bei der Abfrage mit sys.sysprocesses
wird also nur "im Moment" gesucht. Und die Abfrage, die verwendet sys.dm_exec_query_stats
wird, untersucht hauptsächlich (möglicherweise), was seit dem letzten Neustart des SQL Server-Dienstes (oder offensichtlich seit dem Neustart des Systems) geschehen ist. Für die allgemeine Leistungsanalyse scheint dies sys.dm_exec_query_stats
weitaus besser zu sein, aber es werden immer wieder nützliche Informationen gelöscht. In beiden Fällen müssen Sie auch die Punkte berücksichtigen, die @Aaron in den (seitdem entfernten) Fragenkommentaren bezüglich der Genauigkeit des Werts "database_id" gemacht hat (dh, es gibt nur die aktive Datenbank wieder, die den Code initiiert hat , nicht unbedingt dort, wo das "Problem" auftritt).
Aber, wenn Sie nur brauchen / wollen ein Gefühl dafür zu bekommen , was in allen Datenbanken im Augenblick geschieht, möglicherweise , weil die Dinge verlangsamen jetzt nach unten, sind Sie besser dran , die Kombination der Verwendung sys.dm_exec_connections
, sys.dm_exec_sessions
und sys.dm_exec_requests
(und nicht die veralteten sys.sysprocesses
). Denken Sie nur daran, dass Sie nach Abfragen suchen , nicht nach Datenbanken , da Abfragen über mehrere Datenbanken hinweg verknüpft werden können, UDFs aus einer oder mehreren Datenbanken enthalten usw.
BEARBEITEN:
Wenn das Hauptanliegen darin besteht, die Anzahl der CPU-Verbraucher zu verringern, suchen Sie nach den Abfragen, die die meiste CPU beanspruchen, da Datenbanken tatsächlich keine CPU beanspruchen im Besitz eines anderen Kunden).
Mit der folgenden Abfrage können Sie Abfragen mit einer hohen durchschnittlichen CPU-Auslastung identifizieren. Die Daten in der DMV "query_stats" werden komprimiert, da diese Datensätze dieselbe Abfrage (ja, dieselbe Teilmenge des Abfragestapels) mehrmals mit jeweils einem anderen Ausführungsplan anzeigen können.
;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 Millisekunden?