您如何判断SQL Server 2005数据库中哪些表占用了最多的空间?


90

您如何判断SQL Server 2005数据库中哪些表占用了最多的空间?

我确定有一些显示该信息的系统存储过程。

我拥有一个从1tb增长到23tb的TEST数据库。当前,我们正在数据库中进行许多客户端转换测试,这需要多次运行相同的转换存储过程。它确实执行DELETE,这肯定会增加事务日志。但这让我开始思考这个问题。

信息

最大的问题是dbo.Download表,它创建了实际上不需要的海量存储,在删除之前我有3GB,然后是52MB;)


2
Marc_S和Barry的答案非常出色,因此我对他们两个都进行了投票,并等着看哪个获得了最多的投票,因此我可以用“ Accepted Answer”来奖励那个。但是他们俩并列5,所以我只选了一个,但我都用了。非常感谢Marc_S和Barry!
Gerhard Weiss,2010年

Answers:


207

尝试以下脚本-它会列出数据库中所有表的行数和数据行使用的空间(以及使用的总空间):

SELECT 
 t.NAME AS TableName,
 i.name AS indexName,
 SUM(p.rows) AS RowCounts,
 SUM(a.total_pages) AS TotalPages, 
 SUM(a.used_pages) AS UsedPages, 
 SUM(a.data_pages) AS DataPages,
 (SUM(a.total_pages) * 8) / 1024 AS TotalSpaceMB, 
 (SUM(a.used_pages) * 8) / 1024 AS UsedSpaceMB, 
 (SUM(a.data_pages) * 8) / 1024 AS DataSpaceMB
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
WHERE 
 t.NAME NOT LIKE 'dt%' AND
 i.OBJECT_ID > 255 AND  
 i.index_id <= 1
GROUP BY 
 t.NAME, i.object_id, i.index_id, i.name 
ORDER BY 
 OBJECT_NAME(i.object_id) 

6
+1辉煌。请注意,这不包括数据索引的大小。但是对我来说,它完成了工作。
Erick Robertson

39
我不知道,但是如果您使用的是Management Studio,也可以右键单击数据库,然后转到“报告”->“按表划分磁盘使用量”以得到相同的结果。
rossisdead 2015年

@rossisdead,这是一条有趣的信息。谢谢!
Nickmaovich

我得到“表'sys.tables'不存在”
Seano

@Seano:您使用的是哪个SQL Server版本?(运行SELECT @@VERSION查找)您的数据库具有什么数据库兼容性级别?
marc_s

33

使用sp_spacedUsed

Exec sp_spaceused N'YourTableName'

或者,如果要对sp_spaceused数据库中的每个表执行,则可以使用以下SQL:

set nocount on
create table #spaceused (
  name nvarchar(120),
  rows char(11),
  reserved varchar(18),
  data varchar(18),
  index_size varchar(18),
  unused varchar(18)
)

declare Tables cursor for
  select name
  from sysobjects where type='U'
  order by name asc

OPEN Tables
DECLARE @table varchar(128)

FETCH NEXT FROM Tables INTO @table

WHILE @@FETCH_STATUS = 0
BEGIN
  insert into #spaceused exec sp_spaceused @table
  FETCH NEXT FROM Tables INTO @table
END

CLOSE Tables
DEALLOCATE Tables 

select * from #spaceused
drop table #spaceused

exec sp_spaceused

上面的SQL是从这里


7
对于较新版本的SQL Server,您也可以使用exec sp_msforeachtable 'exec sp_spaceused N''?'''
JNK 2010年

1
@JNK sp_msforeachtable因为至少SQL Server 2000中存在
SQLMenace

@SQLMenace-感谢您提供信息。在发布之前,我没有研究它的年龄,但是由于它没有记录,因此不确定是否会找到它。
JNK

4
一个稍微简单的例子:你可以逃脱跳过高管和花哨的报价,这样做只是sp_msforeachtable 'sp_spaceused [?]'如果你喜欢。验证回SQL2000。
2012年

这种方法标记的问题是它不会作为单个结果集返回
Paul

7

Rossisdead的评论对我来说是最好的回答,我希望它不会被掩盖。这将是有用的人喜欢我,不要试图脚本解决方案(在OP并没有要求一个代码片段)

如果您使用的是Management Studio,也可以右键单击数据库,然后转到“报告”->“按表划分磁盘使用量”以获得相同的结果


需要强调的是:右键单击数据库而不是服务器实例
dhollenbeck '18

4

感谢@marc_s的答案。我需要知道数据与索引空间的关系,因此我继续并扩展了查询以包括该内容。

SELECT TableName
    , SUM(DataRowCounts) AS DataRowCounts
    , SUM(DataTotalSpaceGB) AS DataTotalSpaceGB
    , SUM(DataSpaceUsedGB) AS DataSpaceUsedGB
    , SUM(DataUnusedSpaceGB) AS DataUnusedSpaceGB
    , SUM(IndexRowCounts) AS IndexRowCounts
    , SUM(IndexTotalSpaceGB) AS IndexTotalSpaceGB
    , SUM(IndexSpaceUsedGB) AS IndexSpaceUsedGB
    , SUM(IndexUnusedSpaceGB) AS IndexUnusedSpaceGB
    , SUM(DataTotalSpaceGB) + SUM(IndexTotalSpaceGB) AS TotalSpaceGB
FROM
(
SELECT t.NAME AS TableName
    , i.type_desc AS IndexType
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataTotalSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS DataSpaceUsedGB    
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS DataUnusedSpaceGB
    , CASE WHEN i.type_desc IN ('CLUSTERED', 'CLUSTERED COLUMNSTORE', 'HEAP') THEN SUM(p.Rows) ELSE 0 END AS DataRowCounts
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexTotalSpaceGB
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.used_pages) * 8) / 1024.00), 2)/1000 AS NUMERIC(36, 2))  ELSE 0 END AS IndexSpaceUsedGB    
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN CAST(ROUND(((SUM(a.total_pages) - SUM(a.used_pages)) * 8) / 1024.00, 2)/1000 AS NUMERIC(36, 2)) ELSE 0 END AS IndexUnusedSpaceGB  
    , CASE WHEN i.type_desc = 'NONCLUSTERED' THEN SUM(p.Rows) ELSE 0 END AS IndexRowCounts
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 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
    AND s.Name = 'dbo' --update this filter
    AND t.Name = 'MyTable'
GROUP BY t.Name
    , i.type_desc
) x
GROUP BY TableName
ORDER BY TotalSpaceGB DESC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.