Dro*_*onz 10 sql-server ssms sql-server-2008-r2 database-size
我有一个 SQL Server 2008 R2 数据库正在被几个部署的程序使用。
问题:有没有一种简单的方法来显示每个表消耗多少空间,对于数据库中的所有表,并区分逻辑空间和磁盘空间?
如果我使用 SSMS (Management Studio),则为数据库显示的存储属性读取 167 MB,其中 3 MB“可用”(大小合适,但我担心 3 MB 可用 - 这是一个需要关注的限制吗? ,假设我知道我有足够的磁盘空间?)
我可以钻进每张桌子,但这需要永远做。
我知道我可以编写自己的查询并进行测试,但我想知道是否已经有一种简单的(内置的?)方法可以做到这一点。
Nel*_*son 12
已在 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
Run Code Online (Sandbox Code Playgroud)
链接到@Nelson 并由其复制的查询不准确:它忽略了索引视图、全文索引、XML 索引等。
如果您想要一个包含所有内容而不执行sp_spaceusedvia的查询sp_MSForEachTable,那么我已经发布了它的两个变体(一个在 DBA.StackExchange 上,另一个在 StackOverflow 上),所以我不会在这里复制它们:
只是为了好玩,这里有一个查询,它将生成与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
Run Code Online (Sandbox Code Playgroud)
好吧,因为我真的很讨厌自己,所以我写了一个查询,它将生成报告的结果,将其格式化为 HTML 表格,然后作为电子邮件发送。匹配报告背景颜色留给读者作为练习。
declare @subject nvarchar(25) = 'Disk Usage by Top Tables';
declare @recipients nvarchar(25) = 'mailbox@example.com';
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, '<', '<'), '>', '>')
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
Run Code Online (Sandbox Code Playgroud)