どのセッションがどの一時テーブルを保持しているかを見つける


14

一時データベースがいっぱいになったSQL Server 2005データベースがあります。SQL Server Management Studioにアクセスすると、tempdbのすべての一時テーブルを確認できます。どのセッションがどの一時テーブルを保持しているかを知ることはできますか?理想的には、各セッションで使用される一時テーブルをリストするクエリです。

おかげで、


1
一時データベースのスペースを使用している特定のユーザーを追跡します。それは、我々がに興味があるのtempdbの現在のタスクの消費である。
SQLMIKE

回答:


16

私は、2007年にConnectに何かを組み込むことを求めました。これは、2008年のリリースでは拒否され、その後数年前にコネクトが亡くなるまで無視されました。私はSQL Serverの新しいフィードバックサイトでそれを見つけようとしましが、その検索は絶対的なゴミ収集の火です。私のリクエストのタイトルは「一時テーブルをsession_idにマップするdmv」でした-検索はORしか実行できないため、「一時テーブルをマップ」は118ページの結果を返します。グーグルは、彼らがコネクトを殺したとき、アイテムがカットをしなかったと提案するようです。

それまでの間、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)

このJonathan Kehayiasのブログ投稿から恥知らずに持ち上げられました

スペース使用量を判別するには、これをさらに拡張して、次のようなビューからデータに結合できます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)

ここでの問題は、クエリテキストでテーブル名を関連付けることです。ほとんどの場合、ユーザーはまだそのテーブルに対してクエリを実行していないので、これは実用的ではありません(作成または設定したテーブルを実行していることを気にしないでください)。

ただし、これは他のリーダー(またはアップグレード時のリーダー)のためであり、#tempテーブルがヒープの場合、2012 + のデフォルトトレースは一時テーブルオブジェクトの作成を追跡しなくなります。それが偶然なのか、2012年からすべての一時テーブルに現在マイナスがあるobject_idという事実に直接関連しているのかはわかりません。もちろん、この情報を収集および追跡するために拡張イベントに移動することもできますが、これはおそらく手動による作業の多くです(そして、これが追跡されなくなったことを確認しました-選択できない場合があります拡張イベントでアップ)。デフォルトのトレース PKまたはその他の制約で作成された、または作成イベントの後に追加された制約またはインデックスで作成された#tempテーブルを選択しますが、上記の時間ベースの制限を緩和する必要があります(インデックスは、100ミリ秒よりはるか後に作成できます作成)。

このサイトで役立つその他の回答:

SQL Server 2012以降でこの情報を追跡するためのカスタム拡張イベントセッションを使用して、これについてもブログを書いています。

そして、Paul Whiteは、直接ページを読むことについてブログを書いています(気の弱い人のためではなく、決して自動化するのも簡単ではありません)。


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;

このクエリは、割り当てられたページ/割り当て解除されたページ、タスクのSQLテキスト(利用可能な場合)など、上位10のタスクに関する有用な情報を引き出します。

これらのDMVには優れた情報が満載なので、より多くのデータが必要な場合は、プルするデータと組み合わせることができます。ただし、これは、現在のtempdb消費タスクのトラブルシューティングの開始点になるはずです。


ありがとうございます。奇妙なことに、tempdbで「上位テーブル別のディスク使用量」レポートを実行すると、最もスペースを使用しているテーブルがst.textに表示されません。クエリを実行した後もテーブルは残っています。
SQLMIKE 2014年

1
@SQLMIKEは、どのテーブルが最大であるかを知りたいだけの場合は、から取得できますtempdb.sys.dm_db_partition_stats。残念ながら、どのコピーが#some_table_nameどのユーザーに属しているかを実際に確認することはできません。また、常にそのテーブルを参照するステートメントテキストをいつでもプルすることはできません。これは、ユーザーが現在実行しているクエリではない場合があります。あなたはこれこれ
アーロン・バートランド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.