Temukan sesi mana yang memegang tabel sementara mana

14

Kami memiliki database SQL Server 2005, temp database telah penuh. Dengan masuk ke SQL Server Management Studio saya bisa melihat semua tabel sementara di tempdb. Apakah mungkin untuk memberitahu sesi mana yang memegang tabel temp yang mana? Idealnya kueri yang akan mencantumkan tabel temp yang digunakan oleh setiap sesi.

Terima kasih,

SQLMIKE
sumber
1
Kami ingin melacak pengguna tertentu yang menggunakan ruang dalam basis data temp. Ini adalah konsumsi tugas tempdb saat ini yang kami minati.
SQLMIKE

Jawaban:

16

Saya meminta sesuatu untuk dibangun kembali pada tahun 2007, di Connect. Ini ditolak untuk rilis 2008, dan kemudian diabaikan, sampai Connect meninggal beberapa tahun yang lalu. Saya mencoba untuk menemukannya di situs umpan balik baru untuk SQL Server , tetapi pencarian itu adalah api tempat sampah mutlak. Judul permintaan saya adalah "dmv untuk memetakan tabel temp ke session_id" - karena pencarian hanya dapat melakukan ATAU, "peta temp table" mengembalikan 118 halaman hasil. Google tampaknya menyarankan item tersebut tidak memotong ketika mereka membunuh Connect .

Sementara itu, untuk SQL Server 2005 dan 2008, Anda harus dapat menarik informasi ini dari jejak default:

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)

Tanpa malu-malu diangkat dari posting blog Jonathan Kehayias ini .

Untuk menentukan penggunaan ruang, Anda dapat lebih lanjut meningkatkannya untuk bergabung dalam data dari tampilan seperti sys.db_db_partition_stats- misalnya:

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)

Masalahnya di sini adalah mencoba menghubungkan nama tabel dengan teks kueri; ini tidak praktis, karena sebagian besar waktu, pengguna masih tidak menjalankan kueri terhadap tabel itu (apalagi masih menjalankan yang membuat / mengisi itu).

Namun, dan ini untuk pembaca lain (atau untuk Anda saat Anda meningkatkan), jejak default di 2012+ tidak lagi melacak pembuatan objek temp table , jika tabel #temp adalah heap. Tidak yakin apakah itu kebetulan atau terkait langsung dengan fakta bahwa mulai tahun 2012 semua tabel temp sekarang memiliki negatifobject_id . Anda tentu saja dapat pindah ke Acara yang Diperpanjang untuk membantu Anda mengumpulkan dan melacak informasi ini, tetapi itu mungkin banyak pekerjaan manual (dan saya hanya memverifikasi bahwa ini tidak lagi dilacak dalam jejak - Anda mungkin tidak dapat mengambilnya di Extended Events juga). Jejak default akan mengambil tabel #temp yang dibuat dengan PK atau kendala lainnya, atau dengan kendala atau indeks ditambahkan setelah acara pembuatan, tetapi kemudian Anda harus melonggarkan pembatasan berbasis waktu di atas (indeks dapat dibuat lebih dari 100 ms setelah penciptaan).

Beberapa jawaban lain di situs ini yang mungkin berguna:

Saya juga membuat blog tentang hal ini, dengan sesi Acara yang diperluas khusus untuk melacak informasi ini di SQL Server 2012 dan lebih tinggi:

Dan Paul White telah menulis blog tentang membaca halaman secara langsung (tidak hanya untuk orang yang lemah hati, juga tidak mudah untuk diotomatisasi dengan cara apa pun):

Aaron Bertrand
sumber
5

Inilah kueri yang akan membantu Anda memulai mencari informasi yang Anda cari:

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;

Kueri ini menarik informasi berguna untuk 10 tugas teratas, seperti halaman yang dialokasikan / tidak dialokasikan, teks SQL tugas (jika tersedia), dll.

DMV ini penuh dengan informasi hebat, jadi jika Anda memerlukan lebih banyak data maka Anda dapat mencampur dan mencocokkan dengan apa yang Anda tarik. Tetapi ini harus menjadi titik awal untuk pemecahan masalah tugas-tugas konsumsi tempdb saat ini.

Thomas Stringer
sumber
Terima kasih itu terlihat cukup bagus. Yang aneh adalah jika saya menjalankan laporan 'Disk Usage by Top Tables' pada tempdb, tabel yang menggunakan sebagian besar ruang tidak muncul di st.text. Tabel masih ada setelah saya menjalankan kueri.
SQLMIKE
1
@ SQLMIKE jika Anda hanya ingin tahu tabel mana yang terbesar, Anda bisa mendapatkannya tempdb.sys.dm_db_partition_stats. Sayangnya, Anda tidak dapat benar-benar mengetahui salinan #some_table_namemilik pengguna mana, juga Anda tidak selalu dapat menarik teks pernyataan yang merujuk tabel itu pada waktu tertentu - yang mungkin bukan kueri yang sedang dijalankan pengguna. Anda mungkin ingin melihat ini dan ini
Aaron Bertrand