Frage

Ist es möglich, eine Aufschlüsselung der CPU-Auslastung zu erhalten? nach Datenbank?

Ich suche idealerweise nach einer Schnittstelle vom Typ Task-Manager für SQL Server, aber anstatt auf die CPU-Auslastung jeder PID zu achten (wie taskmgr) oder jede SPID (wie spwho2k5), möchte ich die gesamte CPU-Auslastung jeder Datenbank anzeigen.Gehen Sie von einer einzelnen SQL-Instanz aus.

Mir ist klar, dass Tools geschrieben werden könnten, um diese Daten zu sammeln und darüber zu berichten, aber ich frage mich, ob es ein Tool gibt, mit dem ich eine Live-Ansicht davon sehen kann, welche Datenbanken am meisten dazu beitragen sqlservr.exe CPU-Last.

War es hilfreich?

Lösung

Irgendwie.Sehen Sie sich diese Abfrage an:

SELECT total_worker_time/execution_count AS AvgCPU  
, total_worker_time AS TotalCPU
, total_elapsed_time/execution_count AS AvgDuration  
, total_elapsed_time AS TotalDuration  
, (total_logical_reads+total_physical_reads)/execution_count AS AvgReads 
, (total_logical_reads+total_physical_reads) AS TotalReads
, execution_count   
, SUBSTRING(st.TEXT, (qs.statement_start_offset/2)+1  
, ((CASE qs.statement_end_offset  WHEN -1 THEN datalength(st.TEXT)  
ELSE qs.statement_end_offset  
END - qs.statement_start_offset)/2) + 1) AS txt  
, query_plan
FROM sys.dm_exec_query_stats AS qs  
cross apply sys.dm_exec_sql_text(qs.sql_handle) AS st  
cross apply sys.dm_exec_query_plan (qs.plan_handle) AS qp 
ORDER BY 1 DESC

Dadurch erhalten Sie die Abfragen im Plan-Cache in der Reihenfolge, wie viel CPU sie verbraucht haben.Sie können dies regelmäßig ausführen, beispielsweise in einem SQL-Agent-Auftrag, und die Ergebnisse in eine Tabelle einfügen, um sicherzustellen, dass die Daten nach Neustarts bestehen bleiben.

Wenn Sie die Ergebnisse lesen, werden Sie wahrscheinlich erkennen, warum wir diese Daten nicht direkt einer einzelnen Datenbank zuordnen können.Erstens kann eine einzelne Abfrage auch ihre wahre übergeordnete Datenbank verbergen, indem sie Tricks wie diesen anwendet:

USE msdb
DECLARE @StringToExecute VARCHAR(1000)
SET @StringToExecute = 'SELECT * FROM AdventureWorks.dbo.ErrorLog'
EXEC @StringToExecute

Die Abfrage würde in MSDB ausgeführt, aber die Ergebnisse würden von AdventureWorks abgefragt.Wo sollen wir den CPU-Verbrauch zuordnen?

Es wird schlimmer, wenn Sie:

  • Verbinden Sie mehrere Datenbanken
  • Führen Sie eine Transaktion in mehreren Datenbanken aus, und der Sperraufwand erstreckt sich über mehrere Datenbanken
  • Führen Sie SQL-Agent-Jobs in MSDB aus, die in MSDB „funktionieren“, aber einzelne Datenbanken sichern

Es geht immer weiter.Aus diesem Grund ist es sinnvoll, die Leistung auf Abfrageebene und nicht auf Datenbankebene zu optimieren.

In SQL Server 2008R2 hat Microsoft Leistungsverwaltungs- und App-Verwaltungsfunktionen eingeführt, die es uns ermöglichen, eine einzelne Datenbank in einem verteilbaren und bereitstellbaren DAC-Paket zu packen, und es handelt sich um vielversprechende Funktionen, die die Verwaltung der Leistung einzelner Datenbanken und ihrer Anwendungen erleichtern.Allerdings erfüllt es immer noch nicht das, was Sie suchen.

Weitere Informationen finden Sie im T-SQL-Repository im SQL Server-Wiki von Toad World (früher bei SQLServerPedia).

Am 29.01. aktualisiert, um Gesamtzahlen statt nur Durchschnittswerte einzubeziehen.

Andere Tipps

SQL Server (ab 2000) installiert Leistungsindikatoren (sichtbar über Performance Monitor oder Perfmon).

Eine der Zählerkategorien (aus einer SQL Server 2005 -Installation lautet :) - SQLServer: Datenbanken

Mit einer Instanz für jede Datenbank.Die verfügbaren Zähler bieten jedoch keinen CPU-Auslastungszähler oder etwas Ähnliches, obwohl es einige Ratenzähler gibt, die Sie verwenden könnten, um eine gute Schätzung der CPU zu erhalten.Beispiel: Wenn Sie zwei Datenbanken haben und die gemessene Rate 20 Transaktionen/Sek. auf Datenbank A und 80 Transaktionen/Sek. auf Datenbank B beträgt, dann wissen Sie, dass A ungefähr 20 % der gesamten CPU ausmacht, und B trägt zu weiteren 80 % bei.

Hier gibt es einige Mängel, da davon ausgegangen wird, dass die gesamte geleistete Arbeit CPU-gebunden ist, was bei Datenbanken natürlich nicht der Fall ist.Aber das wäre meiner Meinung nach ein Anfang.

Hier ist eine Abfrage, die die tatsächliche Datenbank anzeigt, die eine hohe Auslastung verursacht.Es ist auf den Abfragecache angewiesen, der in Szenarien mit wenig Arbeitsspeicher häufig geleert werden kann (was die Abfrage weniger nützlich macht).

select dbs.name, cacheobjtype, total_cpu_time, total_execution_count from
    (select top 10
        sum(qs.total_worker_time) as total_cpu_time,  
        sum(qs.execution_count) as total_execution_count, 
        count(*) as  number_of_statements,  
        qs.plan_handle
    from  
        sys.dm_exec_query_stats qs 
    group by qs.plan_handle
    order by sum(qs.total_worker_time) desc
    ) a
inner join 
(SELECT plan_handle, pvt.dbid, cacheobjtype
FROM (
    SELECT plan_handle, epa.attribute, epa.value, cacheobjtype
    FROM sys.dm_exec_cached_plans 
        OUTER APPLY sys.dm_exec_plan_attributes(plan_handle) AS epa
     /* WHERE cacheobjtype = 'Compiled Plan' AND objtype = 'adhoc' */) AS ecpa 
PIVOT (MAX(ecpa.value) FOR ecpa.attribute IN ("dbid", "sql_handle")) AS pvt
) b on a.plan_handle = b.plan_handle
inner join sys.databases dbs on dbid = dbs.database_id

Ich denke, die Antwort auf Ihre Frage lautet nein.

Das Problem besteht darin, dass eine Aktivität auf einem Computer mehrere Datenbanken belasten kann.Wenn ich einen Prozess habe, der aus einer Konfigurations-Datenbank liest, sich in einer Protokollierungs-Datenbank protokolliert und Transaktionen je nach Typ in und aus verschiedenen Datenbanken verschiebt, wie partitioniere ich dann die CPU-Nutzung?

Sie könnten die CPU-Auslastung durch die Transaktionslast dividieren, aber das ist wiederum eine grobe Kennzahl, die Sie möglicherweise in die Irre führt.Wie würden Sie beispielsweise den Transaktionsprotokollversand von einer Datenbank auf eine andere aufteilen?Liegt die CPU-Last beim Lesen oder beim Schreiben?

Schauen Sie sich besser die Transaktionsrate einer Maschine und die dadurch verursachte CPU-Last an.Sie können auch gespeicherte Prozeduren profilieren und prüfen, ob eine davon übermäßig viel Zeit in Anspruch nimmt.Allerdings erhalten Sie dadurch nicht die gewünschte Antwort.

Unter Berücksichtigung aller oben genannten Punkte.
Ab SQL Server 2012 (vielleicht 2008?) gibt es eine Spalte Datenbank_ID In sys.dm_exec_sessions.
Es ermöglicht uns eine einfache Berechnung der CPU für jede Datenbank derzeit verbunden Sitzungen.Wenn die Sitzung getrennt wurde, sind die Ergebnisse verschwunden.

select session_id, cpu_time, program_name, login_name, database_id 
  from sys.dm_exec_sessions 
 where session_id > 50;

select sum(cpu_time)/1000 as cpu_seconds, database_id 
 from sys.dm_exec_sessions 
group by database_id
order by cpu_seconds desc;

Schauen Sie mal rein SQL Sentry.Es bietet alles, was Sie brauchen, und noch mehr.

Grüße, Lieven

Haben Sie sich den SQL-Profiler angeschaut?

Nehmen Sie die Standardvorlage „T-SQL“ oder „Gespeicherte Prozedur“ und passen Sie die Felder an, um sie nach der Datenbank-ID zu gruppieren (ich denke, Sie müssen die Nummer verwenden, Sie erhalten nicht den Datenbanknamen, aber das ist mit exec sp_databases leicht herauszufinden um die Liste zu bekommen)

Führen Sie dies eine Weile aus und Sie erhalten die Gesamtzahl der CPUs/Datenträger-IO/Wartezeit usw.Dadurch können Sie den Anteil der von jeder Datenbank genutzten CPU ermitteln.

Wenn Sie gleichzeitig den PerfMon-Zähler überwachen (die Daten in einer SQL-Datenbank protokollieren) und dasselbe für den SQL Profiler tun (in der Datenbank protokollieren), können Sie Mai in der Lage sein, die beiden miteinander in Beziehung zu setzen.

Dennoch sollte es Ihnen einen ausreichenden Anhaltspunkt dafür geben, welche DB es wert ist, genauer betrachtet zu werden.Machen Sie dann dasselbe noch einmal mit genau dieser Datenbank-ID und suchen Sie nach den teuersten SQL-/gespeicherten Prozeduren.

Bitte überprüfen Sie diese Abfrage:

SELECT 
    DB_NAME(st.dbid) AS DatabaseName
    ,OBJECT_SCHEMA_NAME(st.objectid,dbid) AS SchemaName
    ,cp.objtype AS ObjectType
    ,OBJECT_NAME(st.objectid,dbid) AS Objects
    ,MAX(cp.usecounts)AS Total_Execution_count
    ,SUM(qs.total_worker_time) AS Total_CPU_Time
    ,SUM(qs.total_worker_time) / (max(cp.usecounts) * 1.0) AS Avg_CPU_Time 
FROM sys.dm_exec_cached_plans cp 
INNER JOIN sys.dm_exec_query_stats qs 
    ON cp.plan_handle = qs.plan_handle
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
WHERE DB_NAME(st.dbid) IS NOT NULL
GROUP BY DB_NAME(st.dbid),OBJECT_SCHEMA_NAME(objectid,st.dbid),cp.objtype,OBJECT_NAME(objectid,st.dbid) 
ORDER BY sum(qs.total_worker_time) desc
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top