web-dev-qa-db-fra.com

Rechercher quelle session contient quelle table temporaire

Nous avons une base de données SQL Server 2005, la base de données temporaire est pleine. En allant dans SQL Server Management Studio, je peux voir toutes les tables temporaires dans tempdb. Est-il possible de dire quelle session contient quelle table temporaire? Idéalement, une requête répertoriant les tables temporaires utilisées par chaque session.

Merci,

14
SQLMIKE

J'ai demandé que quelque chose soit intégré en 2007, sur Connect. Cela a été rejeté pour la version 2008, puis ignoré, jusqu'à ce que Connect meure il y a quelques années. J'ai essayé de le trouver sur le nouveau site de commentaires pour SQL Server , mais cette recherche est un véritable incendie de poubelle. Le titre de ma demande était "dmv pour mapper la table temporaire à session_id" - puisque la recherche ne peut faire que OU, "la table temporaire de la carte" renvoie 118 pages de résultats. Google semble suggérer que l'élément n'a pas été coupé lorsqu'il a tué Connect .

En attendant, pour SQL Server 2005 et 2008, vous devriez pouvoir extraire ces informations de la trace par défaut:

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)

Sans vergogne tiré de ce billet de blog de Jonathan Kehayias.

Pour déterminer l’utilisation de l’espace, vous pouvez encore l’améliorer pour intégrer des données à partir de vues telles que sys.db_db_partition_stats - par exemple.:

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)

Le problème ici est d'essayer de corréler un nom de table par le texte de la requête; ce n'est tout simplement pas pratique, car la plupart du temps, l'utilisateur n'exécute pas encore exécutant une requête sur cette table (sans parler de l'exécution de celle qui l'a créée/remplie).

Cependant, et ceci est pour d'autres lecteurs (ou pour vous lorsque vous effectuez une mise à niveau), la trace par défaut en 2012+ ne suit plus la création d'objets de table temporaire , si la table #temp est un tas. Je ne sais pas si c'est une coïncidence ou directement liée au fait qu'à partir de 2012 toutes les tables temporaires ont maintenant un object_id . Vous pouvez bien sûr passer aux événements étendus pour vous aider à collecter et suivre ces informations, mais cela représente peut-être beaucoup de travail manuel (et j'ai seulement vérifié que ce n'est plus suivi dans la trace - vous ne pourrez peut-être pas les récupérer) dans les événements étendus). La trace par défaut will récupère les tables #temp créées avec un PK ou une autre contrainte, ou avec des contraintes ou des index ajoutés après l'événement de création, mais vous devrez ensuite assouplir le temps restrictions ci-dessus (un index peut être créé bien plus tard que 100 ms après sa création).

Quelques autres réponses sur ce site qui peuvent être utiles:

J'ai également blogué à ce sujet, avec une session d'événements étendus personnalisée pour suivre ces informations dans SQL Server 2012 et versions ultérieures:

Et Paul White a blogué sur la lecture directe des pages (pas exactement pour les faibles de cœur, ni facile à automatiser en aucune façon):

16
Aaron Bertrand

Voici une requête qui devrait vous aider à découvrir les informations que vous recherchez:

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;

Cette requête extrait des informations utiles pour les 10 principales tâches, telles que les pages allouées/désallouées, le texte SQL des tâches (si disponible), etc.

Ces DMV regorgent d'informations, donc si vous avez besoin de plus de données, vous pouvez mélanger et assortir avec ce que vous tirez. Mais cela devrait être un point de départ pour le dépannage des tâches de consommation tempdb actuelles.

5
Thomas Stringer