Finden Sie heraus, welche Sitzung welche temporäre Tabelle enthält

14

Wir haben eine SQL Server 2005-Datenbank, deren temporäre Datenbank voll geworden ist. Wenn ich in SQL Server Management Studio gehe, kann ich alle temporären Tabellen in der Tempdb sehen. Ist es möglich zu erkennen, welche Sitzung welche temporäre Tabelle enthält? Idealerweise eine Abfrage, in der temporäre Tabellen aufgelistet werden, die von jeder Sitzung verwendet werden.

Vielen Dank,

SQLMIKE
quelle
1
Wir möchten den bestimmten Benutzer ausfindig machen, der den Speicherplatz in der temporären Datenbank verwendet. Es ist der aktuelle Tempdb-Verbrauch der Aufgaben, an dem wir interessiert sind.
SQLMIKE

Antworten:

16

Ich habe 2007 darum gebeten, auf Connect etwas einzubauen. Dies wurde für die Veröffentlichung 2008 abgelehnt und anschließend ignoriert, bis Connect vor einigen Jahren starb. Ich habe versucht, es auf der neuen Feedback-Site für SQL Server zu finden , aber diese Suche ist ein absoluter Müllcontainer. Der Titel meiner Anfrage lautete "dmv to map temp table to session_id" - da die Suche nur ODER ausführen kann, gibt "map temp table" 118 Ergebnisseiten zurück. Google scheint zu vermuten, dass der Artikel den Schnitt nicht geschafft hat, als Connect getötet wurde .

In der Zwischenzeit sollten Sie für SQL Server 2005 und 2008 in der Lage sein, diese Informationen aus der Standardablaufverfolgung abzurufen:

DECLARE @FileName VARCHAR(MAX)  

SELECT @FileName = SUBSTRING(path, 0,
   LEN(path)-CHARINDEX('\', REVERSE(path))+1) + '\Log.trc'  
FROM sys.traces   
WHERE is_default = 1;  

SELECT   
     o.name,   
     o.OBJECT_ID,  
     o.create_date, 
     gt.NTUserName,  
     gt.HostName,  
     gt.SPID,  
     gt.DatabaseName,  
     gt.TEXTData 
FROM sys.fn_trace_gettable( @FileName, DEFAULT ) AS gt  
JOIN tempdb.sys.objects AS o   
     ON gt.ObjectID = o.OBJECT_ID  
WHERE gt.DatabaseID = 2 
  AND gt.EventClass = 46 -- (Object:Created Event from sys.trace_events)  
  AND o.create_date >= DATEADD(ms, -100, gt.StartTime)   
  AND o.create_date <= DATEADD(ms, 100, gt.StartTime)

Schamlos aus diesem Jonathan Kehayias Blog-Beitrag entfernt .

Um die Speicherplatznutzung zu bestimmen, können Sie dies weiter verbessern, um Daten aus Ansichten wie sys.db_db_partition_stats- z.

DECLARE @FileName VARCHAR(MAX)  

SELECT @FileName = SUBSTRING(path, 0,
   LEN(path)-CHARINDEX('\', REVERSE(path))+1) + '\Log.trc'  
FROM sys.traces   
WHERE is_default = 1;  

SELECT   
     o.name,   
     o.OBJECT_ID,  
     o.create_date, 
     gt.NTUserName,  
     gt.HostName,  
     gt.SPID,  
     gt.DatabaseName,  
     gt.TEXTData,
     row_count = x.rc,
     used_page_count = x.upc
FROM sys.fn_trace_gettable( @FileName, DEFAULT ) AS gt  
JOIN tempdb.sys.objects AS o   
     ON gt.ObjectID = o.OBJECT_ID
INNER JOIN
(
 SELECT [object_id], SUM(row_count), SUM(used_page_count)
   FROM tempdb.sys.dm_db_partition_stats
   WHERE index_id IN (0,1)
   GROUP BY [object_id]
) AS x(id, rc, upc)
ON x.id = o.[object_id]
WHERE gt.DatabaseID = 2 
  AND gt.EventClass = 46 -- (Object:Created Event from sys.trace_events)  
  AND o.create_date >= DATEADD(ms, -100, gt.StartTime)   
  AND o.create_date <= DATEADD(ms, 100, gt.StartTime)

Das Problem hierbei ist der Versuch, einen Tabellennamen durch Abfragetext zu korrelieren. dies einfach nicht praktikabel, da die meiste Zeit wird der Benutzer nicht noch eine Abfrage der Tabelle ausführt (nie noch etwas dagegen , die man laufen , dass erstellt / es bevölkert).

Dies gilt jedoch auch für andere Leser (oder für Sie beim Upgrade). Die Standardablaufverfolgung in 2012+ verfolgt die Erstellung temporärer Tabellenobjekte nicht mehr , wenn die Tabelle #temp ein Heap ist. Ich binobject_id mir nicht sicher, ob dies ein Zufall ist oder in direktem Zusammenhang mit der Tatsache steht, dass ab 2012 alle temporären Tabellen jetzt negativ sind . Sie können natürlich zu Extended Events wechseln, um diese Informationen zu sammeln und zu verfolgen, aber das ist möglicherweise eine Menge manueller Arbeit (und ich habe nur überprüft, dass dies nicht mehr in der Ablaufverfolgung verfolgt wird - Sie können es möglicherweise nicht auswählen entweder in Extended Events). Die Standardablaufverfolgung wird Nehmen Sie # temp-Tabellen auf, die mit einer PK oder einer anderen Einschränkung oder mit Einschränkungen oder Indizes erstellt wurden, die nach dem Erstellungsereignis hinzugefügt wurden. Dann müssen Sie die oben genannten zeitbasierten Einschränkungen lockern (ein Index kann viel später als 100 ms später erstellt werden Schaffung).

Einige andere Antworten auf dieser Site, die nützlich sein können:

Ich habe auch darüber gebloggt, mit einer benutzerdefinierten Sitzung für erweiterte Ereignisse, um diese Informationen in SQL Server 2012 und höher zu verfolgen:

Und Paul White hat über das direkte Lesen von Seiten gebloggt (nicht gerade für schwache Nerven oder in irgendeiner Weise einfach zu automatisieren):

Aaron Bertrand
quelle
5

Hier ist eine Abfrage, mit der Sie beginnen können, die gesuchten Informationen herauszufinden:

select top 10
    tsu.session_id,
    tsu.request_id,
    r.command,
    s.login_name,
    s.host_name,
    s.program_name,
    total_objects_alloc_page_count = 
        tsu.user_objects_alloc_page_count + tsu.internal_objects_alloc_page_count,
    tsu.user_objects_alloc_page_count,
    tsu.user_objects_dealloc_page_count,
    tsu.internal_objects_alloc_page_count,
    tsu.internal_objects_dealloc_page_count,
    st.text
from sys.dm_db_task_space_usage tsu
inner join sys.dm_exec_requests r
on tsu.session_id = r.session_id
and tsu.request_id = r.request_id
inner join sys.dm_exec_sessions s
on r.session_id = s.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
where tsu.user_objects_alloc_page_count > 0
or tsu.internal_objects_alloc_page_count > 0
order by total_objects_alloc_page_count desc;

Diese Abfrage ruft nützliche Informationen für die Top-10-Aufgaben ab, z. B. zugewiesene / freigegebene Seiten, den SQL-Text der Aufgaben (falls verfügbar) usw.

Diese DMVs sind voller großartiger Informationen. Wenn Sie also mehr Daten benötigen, können Sie diese mit dem, was Sie abrufen, kombinieren. Dies sollte jedoch ein Ausgangspunkt für die Fehlerbehebung bei aktuellen Tempdb-Verbrauchsaufgaben sein.

Thomas Stringer
quelle
Danke, das sieht ziemlich gut aus. Das Seltsame ist, wenn ich einen Bericht über die Datenträgerverwendung nach Top-Tabellen in der Tempdb ausführe, wird die Tabelle, die den meisten Speicherplatz belegt, nicht im st.text angezeigt. Die Tabelle ist noch vorhanden, nachdem ich die Abfrage ausgeführt habe.
SQLMIKE
1
@SQLMIKE Wenn du nur wissen willst, welche Tabelle die größte ist, kannst du das von bekommen tempdb.sys.dm_db_partition_stats. Leider können Sie nicht wirklich sagen, welche Kopie #some_table_namezu welchem ​​Benutzer gehört, und Sie können auch nicht immer einen Anweisungstext abrufen, der zu einem bestimmten Zeitpunkt auf diese Tabelle verweist. Dies ist möglicherweise nicht die Abfrage, die der Benutzer gerade ausführt. Vielleicht möchten Sie dies und das sehen
Aaron Bertrand