Tampilkan data dan penggunaan disk rincian berdasarkan tabel

9

Saya memiliki database SQL Server 2008 R2 yang digunakan oleh beberapa program yang dikerahkan.

Pertanyaan: Apakah ada cara mudah untuk menampilkan berapa banyak ruang yang dikonsumsi setiap tabel, untuk semua tabel dalam database, dan membedakan ruang logis dari ruang disk?

Jika saya menggunakan SSMS (Management Studio), properti penyimpanan yang ditunjukkan untuk database bertuliskan 167 MB dengan 3 MB "tersedia" (tentang ukuran yang tepat, tapi saya khawatir tentang 3 MB yang tersedia - apakah ini batas untuk khawatir tentang , dengan asumsi saya tahu saya memiliki cukup ruang disk?)

Saya dapat menelusuri setiap tabel, tapi itu perlu waktu lama untuk dilakukan.

Saya tahu saya bisa menulis pertanyaan saya sendiri dan mencoba-coba, tetapi saya ingin tahu apakah sudah ada cara (bawaan?) Yang mudah untuk melakukan ini.

Dronz
sumber

Jawaban:

13

Dalam SSMS, klik kanan pada database dan pergi ke "Laporan", "Laporan Standar", "Penggunaan Disk oleh Tabel". Ini akan memberi tahu Anda ukuran total, ukuran data, ukuran indeks, dan ukuran yang tidak digunakan untuk setiap tabel (serta jumlah baris).

nateirvin
sumber
1
Saya belum pernah melihat itu sebelumnya dan saya lebih menyukainya daripada script - kecuali bahwa pada beberapa database gagal karena saya tidak memiliki izin "LIHAT DATABASE STATE" - tetapi script akan bekerja dalam kasus itu. Sosok pergi!
Chris Woodruff
10

Sudah dijawab di Stack Overflow:

SELECT 
    t.NAME AS TableName,
    s.Name AS SchemaName,
    p.rows AS RowCounts,
    SUM(a.total_pages) * 8 AS TotalSpaceKB, 
    SUM(a.used_pages) * 8 AS UsedSpaceKB, 
    (SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
FROM 
    sys.tables t
INNER JOIN      
    sys.indexes i ON t.OBJECT_ID = i.object_id
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id
LEFT OUTER JOIN 
    sys.schemas s ON t.schema_id = s.schema_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
    AND i.OBJECT_ID > 255 
GROUP BY 
    t.Name, s.Name, p.Rows
ORDER BY 
    t.Name
Nelz
sumber
5

Permintaan yang ditautkan ke, dan disalin oleh, @Nelson tidak akurat: ia mengabaikan Tampilan Terindeks, Indeks Teks Lengkap, Indeks XML, dll.

Jika Anda ingin kueri yang akan menyertakan semuanya tanpa mengeksekusi sp_spaceusedmelalui sp_MSForEachTable, maka saya telah memposting dua variasi dari itu (satu di sini di DBA.StackExchange dan yang lainnya di StackOverflow) jadi saya tidak akan menyalinnya di sini:

Solomon Rutzky
sumber
4

Hanya untuk bersenang-senang, inilah pertanyaan yang akan menghasilkan data yang sama dengan laporan dalam jawaban nateirvin

create table #disk_usage
(
    name varchar(128)
    ,rows varchar(20)
    ,reserved varchar(20)
    ,data varchar(20)
    ,index_size varchar(20)
    ,unused varchar(20)
);

exec sp_msforeachtable 'insert into #disk_usage exec sp_spaceused [?]'

select SCHEMA_NAME(st.schema_id) + '.' + du.name 'Table Name'
 ,du.rows '# Records'
 ,du.reserved 'Reserved (KB)'
 ,du.data 'Data (KB)'
 ,du.index_size 'Indexes (KB)'
 ,du.unused 'Unused (KB)'
 from #disk_usage du
left join sys.tables st
on du.name = st.name
order by cast(left(reserved, len(reserved) - 3) as bigint) desc;

drop table #disk_usage

Oke, karena saya benar - benar membenci diri sendiri, saya menulis kueri yang akan menghasilkan hasil laporan, memformatnya sebagai tabel HTML, dan mengirimkannya sebagai email. Menyesuaikan warna latar belakang laporan dibiarkan sebagai latihan untuk pembaca.

declare @subject nvarchar(25) = 'Disk Usage by Top Tables';

declare @recipients nvarchar(25) = '[email protected]';

create table #disk_usage
(
    name varchar(128)
    ,rows varchar(20)
    ,reserved varchar(20)
    ,data varchar(20)
    ,index_size varchar(20)
    ,unused varchar(20)
);

exec sp_msforeachtable 'insert into #disk_usage EXEC sp_spaceused [?]'

declare @body nvarchar(max) = 
'<table cellspacing="0">
    <thead>
        <tr>
            <th>Table Name</th>
            <th># Rows</th>
            <th>Reserved</th>
            <th>Data</th>
            <th>Indexes</th>
            <th>Unused</th>
        </tr>
    </thead>
';

set @body = @body + cast (
    (select '<td style="border: 1px solid black; padding: 2px">' + SCHEMA_NAME(s.schema_id) + '.' + t.name + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + rtrim(ltrim(t.rows)) + ' Rows </td>' -- for some reason this was generating a bunch of extra white space and I'm not going to bother to figure out why
     ,'<td style="border: 1px solid black; padding: 2px">' + t.reserved + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + t.data + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + t.index_size + '</td>'
     ,'<td style="border: 1px solid black; padding: 2px">' + t.unused + '</td>'
     from #disk_usage t
    left join sys.tables s
    on t.name = s.name
    order by cast(left(reserved, len(reserved) - 3) as bigint) desc
    for xml path ('tr'))
as nvarchar(max));

set @body = replace(replace(@body, '&lt;', '<'), '&gt;', '>')
set @body = @body + '</table>'

exec msdb.dbo.sp_send_dbmail 
@profile_name='A Database Mail Profile On The Target Server', 
@recipients=@recipients, 
@subject=@subject,
@body=@body,
@body_format='HTML'

drop table #disk_usage
MikeTheLiar
sumber
1
Wow! Bagian terakhir dari pekerjaan yang dibenci oleh diri sendiri itu luar biasa (bagi orang lain ;-))! Terima kasih telah menambahkan itu. Saya menyesal hanya memiliki satu suara untuk memberikan jawaban ini ...
Dronz
1
:) Saya pikir jika saya harus melalui rasa sakit melakukannya, paling tidak yang bisa saya lakukan adalah menyelamatkan orang lain dari nasib yang sama.
MikeTheLiar