Encuentra qué sesión está sosteniendo qué tabla temporal


14

Tenemos una base de datos SQL Server 2005, la base de datos temporal se ha llenado. Al ingresar a SQL Server Management Studio puedo ver todas las tablas temporales en tempdb. ¿Es posible saber qué sesión tiene qué tabla temporal? Idealmente, una consulta que enumeraría las tablas temporales utilizadas por cada sesión.

Gracias,


1
Nos gustaría rastrear al usuario específico que está utilizando el espacio en la base de datos temporal. Es el consumo de tempdb de las tareas actuales lo que nos interesa.
SQLMIKE

Respuestas:


16

Pedí que se construyera algo en 2007, en Connect. Esto fue rechazado para el lanzamiento de 2008, y posteriormente ignorado, hasta que Connect murió hace unos años. Traté de encontrarlo en el nuevo sitio de comentarios para SQL Server , pero esa búsqueda es un incendio absoluto en el contenedor. El título de mi solicitud era "dmv para asignar la tabla temporal a session_id", ya que la búsqueda solo puede hacer OR, "asignar tabla temporal" devuelve 118 páginas de resultados. Google parece sugerir que el elemento no hizo el corte cuando mataron a Connect .

Mientras tanto, para SQL Server 2005 y 2008, debería poder extraer esta información de la traza predeterminada:

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)

Descaradamente sacado de esta publicación de blog de Jonathan Kehayias .

Para determinar el uso del espacio, puede mejorar esto para unir datos de vistas como sys.db_db_partition_stats, por ejemplo:

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)

El problema aquí es intentar correlacionar un nombre de tabla por texto de consulta; esto simplemente no es práctico, ya que la mayoría de las veces, el usuario todavía no ejecuta una consulta en esa tabla (no importa seguir ejecutando la que la creó / completó).

Sin embargo, y esto es para otros lectores (o para usted cuando actualiza), el rastreo predeterminado en 2012+ ya no rastrea la creación de objetos de la tabla temporal , si la tabla #temp es un montón. No estoy seguro si eso es una coincidencia o está directamente relacionado con el hecho de que a partir de 2012 todas las tablas temporales ahora tienen un resultado negativoobject_id . Por supuesto, podría pasar a Eventos extendidos para ayudarlo a recopilar y rastrear esta información, pero eso es posiblemente una gran cantidad de trabajo manual (y solo he verificado que esto ya no se rastrea en el rastreo; es posible que no pueda recogerlo arriba en eventos extendidos tampoco). La traza predeterminada será seleccione las tablas de #temp creadas con una PK u otra restricción, o con restricciones o índices agregados después del evento de creación, pero luego deberá aflojar las restricciones basadas en el tiempo anteriores (se puede crear un índice mucho más tarde que 100ms después creación).

Algunas otras respuestas en este sitio que pueden ser útiles:

También escribí un blog sobre esto, con una sesión personalizada de eventos extendidos para rastrear esta información en SQL Server 2012 y versiones posteriores:

Y Paul White ha blogueado sobre leer páginas directamente (no exactamente para los débiles de corazón, ni fácil de automatizar de ninguna manera):


5

Aquí hay una consulta que debería ayudarlo a encontrar la información que está buscando:

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;

Esta consulta extrae información útil para las 10 tareas principales, como las páginas asignadas / desasignadas, el texto SQL de las tareas (si está disponible), etc.

Estos DMV están llenos de gran información, por lo que si necesita más datos, puede mezclar y combinar con lo que está obteniendo. Pero este debería ser un punto de partida para solucionar las tareas actuales de consumo de tempdb.


Gracias eso se ve bastante bien. Lo extraño es que si ejecuto un informe de 'Uso de disco por tablas superiores' en el tempdb, la tabla que usa más espacio no aparece en el st.text. La tabla sigue ahí después de ejecutar la consulta.
SQLMIKE

1
@SQLMIKE si solo desea saber qué tabla es la más grande, puede obtenerla tempdb.sys.dm_db_partition_stats. Desafortunadamente, realmente no puede saber qué copia #some_table_namepertenece a qué usuario, ni siempre podrá extraer el texto de la declaración que haga referencia a esa tabla en un momento dado; esa puede no ser la consulta que el usuario está ejecutando actualmente. Es posible que desee ver esto y esto
Aaron Bertrand
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.