Trova quale sessione contiene quale tabella temporanea


14

Abbiamo un database SQL Server 2005 il database temporaneo è diventato pieno. Accedendo a SQL Server Management Studio posso vedere tutte le tabelle temporanee nel tempdb. È possibile dire quale sessione contiene quale tabella temporanea? Idealmente, una query che elenca le tabelle temporanee utilizzate da ciascuna sessione.

Grazie,


1
Vorremmo rintracciare l'utente specifico che sta utilizzando lo spazio nel database temporaneo. È il consumo di tempdb delle attività correnti che ci interessa.
SQLMIKE

Risposte:


16

Ho chiesto qualcosa da costruire nel 2007, su Connect. Questo è stato respinto per la versione 2008 e successivamente ignorato, fino alla morte di Connect alcuni anni fa. Ho provato a trovarlo sul nuovo sito di feedback per SQL Server , ma quella ricerca è un vero incendio del cassonetto. Il titolo della mia richiesta era "dmv per mappare la tabella temporanea su session_id" - poiché la ricerca può fare solo OR, "mappa della tabella temporanea" restituisce 118 pagine di risultati. Google sembra suggerire che l'oggetto non ha effettuato il taglio quando hanno ucciso Connect .

Nel frattempo, per SQL Server 2005 e 2008, dovresti essere in grado di estrarre queste informazioni dalla traccia predefinita:

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)

Senza vergogna sollevato da questo post sul blog di Jonathan Kehayias .

Per determinare l'utilizzo dello spazio, è possibile migliorarlo ulteriormente per unire i dati da viste come sys.db_db_partition_stats, ad esempio:

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)

Il problema qui sta cercando di correlare il nome di una tabella con il testo della query; questo non è pratico, dal momento che la maggior parte delle volte l'utente non sta ancora eseguendo una query su quella tabella (non importa se esegue ancora quella che l'ha creata / popolata).

Tuttavia, e questo vale per altri lettori (o per te quando esegui l' aggiornamento), la traccia predefinita in 2012+ non tiene più traccia della creazione dell'oggetto tabella temporanea , se la tabella #temp è un heap. Non sono sicuro se questa sia una coincidenza o direttamente correlata al fatto che a partire dal 2012 tutte le tabelle temporanee ora hanno un valore negativoobject_id . Ovviamente potresti passare a Eventi estesi per aiutarti a raccogliere e tracciare queste informazioni, ma è probabilmente un sacco di lavoro manuale (e ho solo verificato che questo non è più rintracciato in traccia - potresti non essere in grado di selezionarlo o negli Eventi estesi). La traccia predefinita lo farà raccogliere le tabelle #temp create con un PK o altro vincolo, o con vincoli o indici aggiunti dopo l'evento di creazione, ma poi si dovranno allentare le restrizioni temporali sopra (un indice può essere creato molto più tardi di 100 ms dopo creazione).

Alcune altre risposte su questo sito che potrebbero essere utili:

Ho anche scritto un blog su questo, con una sessione personalizzata di eventi estesi per tenere traccia di queste informazioni in SQL Server 2012 e versioni successive:

E Paul White ha scritto sul blog di leggere direttamente le pagine (non esattamente per i deboli di cuore, né facile da automatizzare in alcun modo):


5

Ecco una query che dovrebbe iniziare a scoprire le informazioni che stai cercando:

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;

Questa query estrae informazioni utili per le prime 10 attività, come le pagine allocate / deallocate, il testo SQL delle attività (se disponibile), ecc.

Questi DMV sono pieni di ottime informazioni, quindi se hai bisogno di più dati puoi mescolarli e abbinarli con ciò che stai estraendo. Ma questo dovrebbe essere un punto di partenza per la risoluzione dei problemi relativi ai consumi di tempdb correnti.


Grazie sembra abbastanza buono. La cosa strana è che se eseguo un rapporto "Uso del disco per tabelle principali" sul tempdb, la tabella che sta utilizzando la maggior parte dello spazio non viene visualizzata nello st.text. La tabella è ancora lì dopo aver eseguito la query.
SQLMIKE,

1
@SQLMIKE se vuoi solo sapere quale tabella è la più grande, puoi ottenerla da tempdb.sys.dm_db_partition_stats. Sfortunatamente non puoi davvero dire quale copia #some_table_nameappartiene a quale utente, né sarai sempre in grado di estrarre il testo dell'istruzione che fa riferimento a quella tabella in un dato momento, che potrebbe non essere la query che l'utente sta attualmente eseguendo. Potresti voler vedere questo e questo
Aaron Bertrand
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.