SQL Server 2008 R2 DMV-Frage

7

Ich habe eine Abfrage, um die Top 10-Abfragen basierend auf den gesamten logischen Lesevorgängen aus der DMV dm_exec_query_stats abzurufen.

SELECT TOP 10 
    SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,
    ((CASE qs.statement_end_offset
    WHEN -1 THEN DATALENGTH(qt.TEXT)
    ELSE qs.statement_end_offset
    END - qs.statement_start_offset)/2)+1),
db_name(qt.dbid) as db_name,
qs.execution_count,
qs.total_logical_reads,
qs.total_worker_time,
qs.total_elapsed_time/1000000 total_elapsed_time_in_S,
SUBSTRING(CONVERT(varchar(19),qs.last_execution_time),1,19)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_logical_reads DESC

Die Abfrage gibt alle angeforderten Informationen zurück, mit Ausnahme des Namens der Datenbank, aus der die Abfrage stammt oder an die sie gerichtet war. Ob ich dm_exec_sql_text oder dm_exec_query_plan verwende, das Ergebnis ist das gleiche.

Datenbankname (qt.dbid) als Datenbankname dm_exec_sql_text

oder

Datenbankname (qp.dbid) als Datenbankname dm_exec_query_plan

Beide geben NULL oder tempdb als Datenbanknamen zurück.

Das gleiche Problem tritt auf, wenn Sie Berichte -> Top-Leistungsabfragen nach durchschnittlicher E / A auswählen.

Geben Sie hier die Bildbeschreibung ein

Der Datenbankname ist leer.

Wenn ich den Abfrageplan jedoch zur Abfrage hinzufüge und dann den Abfrageplan in SSMS öffne, kann ich den Namen der Ursprungsdatenbank anzeigen, indem ich den Mauszeiger über die verschiedenen Indexsuchen, Scans oder RID-Suchvorgänge bewege.

Geben Sie hier die Bildbeschreibung ein

Ich habe festgestellt, dass im Abfrageplan mehrere Datenbanken referenziert sind, z. B. mssqlsystemresource zusammen mit der Trackit-Datenbank

Wenn der Abfrageplan den Namen der Datenbank oder der von der Abfrage betroffenen Datenbanken in meiner Top-10-Liste anzeigen konnte, liegt es nahe, dass ich in der Lage sein sollte, die Namen dieser Datenbanken mithilfe einer DMV abzurufen.

Wie kann ich die Top 10-Abfrage ändern, um den Namen der Datenbank für jede Abfrage abzurufen?

Oder gibt es einen besseren Weg, um die Top-10-Abfragen nach CPU- / E / A- / Speicherauslastung abzurufen und den Datenbanknamen oder die Datenbanknamen für jede der Top-10-Abfragen abzurufen?

Craig Efrein
quelle

Antworten:

8
use dbx;
select foo
from db1.dbo.table
join db2.dbo.table on condition
where some_function();

Diese Abfrage verbrauchte viel CPU und forderte eine große Speicherzuweisung an. In welcher Datenbank? Die gewünschten Informationen existieren einfach nicht als Konzept. Als Mensch mit Einsichtswissen und im Nachhinein könnten Sie wahrscheinlich erklären, warum 75% der CPU auf db1 und 15% auf db2 zurückzuführen sind. Letztendlich können Sie einer Datenbank jedoch nur Abfragen zuweisen. Die Tatsache, dass einige (ok, die meisten) Abfragen zu 100% in einer Datenbank enthalten sind, bedeutet nicht, dass alle Abfrageressourcen einer Datenbank deterministisch zugewiesen werden können.

Aus praktischen Gründen ist es jedoch relativ einfach, genau das zu automatisieren, was Sie in Ihrem Beitrag getan haben: Überprüfen Sie die Pläne und identifizieren Sie alle Standorte der physischen Zugriffsbetreiber. Verwenden Sie diese Informationen, um die Abfrageressourcen einer Datenbank zuzuweisen.

with xmlnamespaces (default 'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
select x.value(N'@NodeId',N'int') as NodeId
    , x.value(N'@PhysicalOp', N'sysname') as PhysicalOp
    , x.value(N'@LogicalOp', N'sysname') as LogicalOp
    , ox.value(N'@Database',N'sysname') as [Database]
    , ox.value(N'@Schema',N'sysname') as [Schema]
    , ox.value(N'@Table',N'sysname') as [Table]
    , ox.value(N'@Index',N'sysname') as [Index]
    , ox.value(N'@IndexKind',N'sysname') as [IndexKind]
    , x.value(N'@EstimateRows', N'float') as EstimateRows
    , x.value(N'@EstimateIO', N'float') as EstimateIO
    , x.value(N'@EstimateCPU', N'float') as EstimateCPU
    , x.value(N'@AvgRowSize', N'float') as AvgRowSize
    , x.value(N'@TableCardinality', N'float') as TableCardinality
    , x.value(N'@EstimatedTotalSubtreeCost', N'float') as EstimatedTotalSubtreeCost
    , x.value(N'@Parallel', N'tinyint') as DOP
    , x.value(N'@EstimateRebinds', N'float') as EstimateRebinds
    , x.value(N'@EstimateRewinds', N'float') as EstimateRewinds
    , st.*
    , pl.query_plan
from sys.dm_exec_query_stats as st
cross apply sys.dm_exec_query_plan (st.plan_handle) as pl
cross apply pl.query_plan.nodes('//RelOp[./*/Object/@Database]') as op(x)
cross apply op.x.nodes('./*/Object') as ob(ox)
Remus Rusanu
quelle
Sehr schön, das habe ich gesucht. Vielen Dank für die schnelle Hilfe.
Craig Efrein