Найти, какая сессия содержит какую временную таблицу

14

У нас есть база данных SQL Server 2005, временная база данных заполнена. Зайдя в SQL Server Management Studio, я вижу все временные таблицы в базе данных tempdb. Можно ли сказать, какая сессия содержит какую временную таблицу? В идеале это запрос, в котором перечислены временные таблицы, используемые каждой сессией.

Спасибо,

SQLMIKE
источник
1
Мы хотели бы отследить конкретного пользователя, который использует пространство во временной базе данных. Нас интересует
текущее задание потребления базы

Ответы:

16

Я попросил что-то встроить еще в 2007 году на Connect. Это было отклонено для выпуска 2008 года и впоследствии игнорировалось, пока Connect не умер несколько лет назад. Я пытался найти его на новом сайте обратной связи для SQL Server , но этот поиск - абсолютный пожар. Заголовок моего запроса был «dmv для сопоставления временной таблицы с session_id» - поскольку поиск может выполнять только ИЛИ, «сопоставить временную таблицу» возвращает 118 страниц результатов. Похоже, Google предлагает, чтобы этот предмет не попал, когда они убили Connect .

Между тем, для SQL Server 2005 и 2008 вы должны быть в состоянии извлечь эту информацию из трассировки по умолчанию:

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)

Бесстыдно взято из этого поста в блоге Джонатана Кехайяса .

Чтобы определить использование пространства, вы можете дополнительно улучшить это, чтобы объединить данные из представлений, таких как sys.db_db_partition_stats- например:

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)

Проблема здесь заключается в попытке сопоставить имя таблицы по тексту запроса; это просто не практично, поскольку в большинстве случаев пользователь по- прежнему не выполняет запрос к этой таблице (не говоря уже о том, чтобы запустить тот, который его создал / заполнил).

Однако, и это для других читателей (или для вас при обновлении), трассировка по умолчанию в 2012+ больше не отслеживает создание объекта временной таблицы , если таблица #temp является кучей. Не уверен, является ли это совпадением или напрямую связано с тем, что начиная с 2012 года все временные таблицы теперь имеют отрицательные значенияobject_id . Конечно, вы можете перейти к Расширенным событиям, чтобы помочь вам собирать и отслеживать эту информацию, но это, возможно, большая ручная работа (и я только убедился, что она больше не отслеживается - вы, возможно, не сможете ее выбрать). в расширенных событиях тоже). Трассировка по умолчанию будет выбрать таблицы #temp, созданные с PK или другим ограничением, или с ограничениями или индексами, добавленными после события создания, но тогда вам придется ослабить ограничения, основанные на времени, указанные выше (индекс можно создать намного позже, чем через 100 мс после создание).

Некоторые другие ответы на этом сайте, которые могут быть полезны:

Я также написал в блоге об этом с помощью специального сеанса расширенных событий для отслеживания этой информации в SQL Server 2012 и более поздних версиях:

А Пол Уайт написал в блоге о чтении страниц напрямую (не для слабонервных и не может быть легко автоматизировано):

Аарон Бертран
источник
5

Вот запрос, который поможет вам начать поиск информации, которую вы ищете:

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;

Этот запрос извлекает полезную информацию для топ-10 задач, таких как выделенные / освобожденные страницы, текст задач SQL (если имеется) и т. Д.

Эти DMV полны полезной информации, поэтому, если вам требуется больше данных, вы можете смешивать и сопоставлять то, что вы тянете. Но это должно стать отправной точкой для устранения неполадок текущих задач потребления базы данных tempdb.

Томас Стрингер
источник
Спасибо, это выглядит довольно хорошо. Странно, если я запускаю отчет «Использование диска по верхним таблицам» в базе данных tempdb, таблица, которая использует больше всего места, не отображается в st.text. Таблица все еще там после того, как я выполню запрос.
SQLMIKE
1
@SQLMIKE, если вы просто хотите узнать, какая таблица самая большая, вы можете получить ее tempdb.sys.dm_db_partition_stats. К сожалению, вы не можете точно сказать, какая копия #some_table_nameпринадлежит какому пользователю, и вы не всегда сможете получить текст инструкции, который ссылается на эту таблицу в любой момент времени - это может быть не тот запрос, который в данный момент выполняет пользователь. Вы могли бы хотеть видеть это и это
Аарон Бертран