Encontre qual sessão está mantendo qual tabela temporária

14

Temos um banco de dados SQL Server 2005, o banco de dados temporário ficou cheio. Ao entrar no SQL Server Management Studio, posso ver todas as tabelas temporárias no tempdb. É possível saber qual sessão está mantendo qual tabela temporária? Idealmente, uma consulta que listaria as tabelas temporárias usadas por cada sessão.

Obrigado,

SQLMIKE
fonte
11
Gostaríamos de rastrear o usuário específico que está usando o espaço no banco de dados temporário. É o consumo de tempdb das tarefas atuais em que estamos interessados.
SQLMIKE

Respostas:

16

Eu pedi que algo fosse construído em 2007, no Connect. Isso foi rejeitado na versão de 2008 e subsequentemente ignorado, até que o Connect morreu alguns anos atrás. Tentei encontrá-lo no novo site de feedback do SQL Server , mas essa pesquisa é um incêndio absoluto no lixão. O título da minha solicitação era "dmv para mapear a tabela temporária para session_id" - como a pesquisa só pode executar OR, "map temp table" retorna 118 páginas de resultados. O Google parece sugerir que o item não foi cortado quando mataram o Connect .

Enquanto isso, para o SQL Server 2005 e 2008, você deve conseguir extrair essas informações do rastreamento padrão:

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)

Desavergonhadamente retirado desta postagem no blog de Jonathan Kehayias .

Para determinar o uso do espaço, você pode aprimorá-lo ainda mais para juntar dados de visualizações como sys.db_db_partition_stats- por exemplo:

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)

O problema aqui é tentar correlacionar um nome de tabela pelo texto da consulta; isso simplesmente não é prático, pois na maioria das vezes, o usuário ainda não está executando uma consulta nessa tabela (não importa ainda executar a que a criou / a preencheu).

No entanto, e isso é para outros leitores (ou para você quando você atualiza), o rastreamento padrão em 2012 ou mais não rastreia mais a criação de objetos de tabela temporária , se a tabela #temp for uma pilha. Não tenho certeza se isso é uma coincidência ou diretamente relacionado ao fato de que a partir de 2012 todas as tabelas temporárias agora têm um negativoobject_id . É claro que você poderia ir para Eventos estendidos para ajudá-lo a coletar e rastrear essas informações, mas isso é possivelmente muito trabalho manual (e verifiquei apenas que isso não é mais rastreado no rastreamento - você pode não conseguir selecioná-las em Eventos estendidos). O rastreio padrão será selecione as #temp tables criadas com uma PK ou outra restrição ou com restrições ou índices adicionados após o evento de criação, mas será necessário diminuir as restrições baseadas em tempo acima (um índice pode ser criado muito depois de 100ms após criação).

Algumas outras respostas neste site que podem ser úteis:

Também escrevi sobre isso em um blog, com uma sessão personalizada de Eventos estendidos para rastrear essas informações no SQL Server 2012 e posteriores:

E Paul White publicou um blog sobre a leitura de páginas diretamente (não exatamente para os fracos de coração, nem fáceis de automatizar de forma alguma):

Aaron Bertrand
fonte
5

Aqui está uma consulta que deve ajudar você a descobrir as informações que procura:

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;

Essa consulta obtém informações úteis para as 10 principais tarefas, como páginas alocadas / desalocadas, o texto SQL das tarefas (se disponível), etc.

Essas DMVs estão cheias de ótimas informações; portanto, se você precisar de mais dados, poderá misturar e combinar com o que está puxando. Mas esse deve ser um ponto de partida para solucionar problemas das tarefas atuais de consumo de tempdb.

Thomas Stringer
fonte
Obrigado, que parece muito bom. O curioso é que, se eu gerar um relatório 'Uso do disco pelas tabelas principais' no tempdb, a tabela que está usando mais espaço não aparece no st.text. A tabela ainda está lá depois que eu executo a consulta.
SQLMIKE 25/03
11
@ SQLMIKE Se você quiser saber qual tabela é a maior, pode obtê-la tempdb.sys.dm_db_partition_stats. Infelizmente, você não pode realmente dizer qual cópia #some_table_namepertence a qual usuário, nem sempre poderá obter o texto da instrução que faz referência a essa tabela a qualquer momento - que pode não ser a consulta que o usuário está executando no momento. Você pode querer ver isso e isso
Aaron Bertrand