我继承了一个相当大的SQL Server数据库。考虑到它包含的数据,它似乎比我预期的要占用更多的空间。

是否有一种简单的方法来确定每个表占用的磁盘空间?


当前回答

如果您只关心数据库中的空浪费空间,而不关心单个表,则可以考虑以下问题:

如果数据库经历了大量的数据插入和删除,可能与ETL情况类似,这将导致数据库中有太多未使用的空间,因为文件组会自动增长,但不会自动收缩。

您可以通过使用数据库的财产页面来查看是否是这种情况。您可以收缩(右键单击数据库>任务>收缩)并收回一些空间。但是,如果根本原因仍然存在,则数据库将增长(并花费额外的时间尝试增长,直到增长到足够的速度,所以不要这样做)

其他回答

 exec  sp_spaceused N'dbo.MyTable'

对于所有表,请使用。。(根据保罗的评论补充)

exec sp_MSForEachTable 'exec sp_spaceused [?]'
CREATE TABLE #tmp_table_info
(
id int identity(1,1),
tblname varchar(200)
);
CREATE TABLE #SpaceUsed 
(
     TableName sysname
    ,NumRows BIGINT
    ,ReservedSpace VARCHAR(50)
    ,DataSpace VARCHAR(50)
    ,IndexSize VARCHAR(50)
    ,UnusedSpace VARCHAR(50)
) 

insert into #tmp_table_info
select s.name+'.'+t.name 
from sys.tables t 
inner join sys.schemas s on t.schema_id = s.schema_id
where t.type = 'U';

declare @min int =1,@max int = 0
select @max = count(*)
from #tmp_table_info
while(@min<=@max)
begin
    declare @tablename varchar(200)
    select @tablename=tblname
    from #tmp_table_info
    where id =@min

    DECLARE @str VARCHAR(500)
    SET @str =  'sp_spaceused '''+@tablename+''''
    INSERT INTO #SpaceUsed 
    EXEC (@str)  
    set @min =@min + 1
end;
select @@SERVERNAME as servername,DB_NAME() as DatabaseName,CONVERT(numeric(18,0),REPLACE(ReservedSpace,' KB','')) / 1024 as ReservedSpace_MB,
CONVERT(numeric(18,0),REPLACE(DataSpace,' KB','')) / 1024 as DataSpace_MB,
CONVERT(numeric(18,0),REPLACE(IndexSize,' KB','')) / 1024 as IndexSpace_MB,
CONVERT(numeric(18,0),REPLACE(UnusedSpace,' KB','')) / 1024 as UnusedSpace_MB from #SpaceUsed
drop table #tmp_table_info
drop table #SpaceUsed

我发现这个查询很容易使用和快速。

select schema_name(tab.schema_id) + '.' + tab.name as [table], 
cast(sum(spc.used_pages * 8)/1024.00 as numeric(36, 2)) as used_mb,
cast(sum(spc.total_pages * 8)/1024.00 as numeric(36, 2)) as allocated_mb
from sys.tables (nolock) tab
inner join sys.indexes (nolock) ind 
    on tab.object_id = ind.object_id
inner join sys.partitions  (nolock) part 
    on ind.object_id = part.object_id and ind.index_id = part.index_id
inner join sys.allocation_units (nolock) spc
    on part.partition_id = spc.container_id
group by schema_name(tab.schema_id) + '.' + tab.name
order by sum(spc.used_pages) desc

如果您使用的是SQL Server Management Studio(SSMS),则可以运行标准报告,而不是运行查询(在我的情况下返回重复的行)

右键单击数据库导航到报告>标准报告>磁盘使用情况(按表)

注意:数据库兼容级别必须设置为90或更高,才能正常工作。看见http://msdn.microsoft.com/en-gb/library/bb510680.aspx

我在marc_s答案的顶部添加了几列:

with fs
as
(
select i.object_id,
        p.rows AS RowCounts,
        SUM(a.total_pages) * 8 AS TotalSpaceKb
from     sys.indexes i 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 
    i.OBJECT_ID > 255 
GROUP BY 
    i.object_id,
    p.rows
)

SELECT 
    t.NAME AS TableName,
    fs.RowCounts,
    fs.TotalSpaceKb,
    t.create_date,
    t.modify_date,
    ( select COUNT(1)
        from sys.columns c 
        where c.object_id = t.object_id ) TotalColumns    
FROM 
    sys.tables t INNER JOIN      
    fs  ON t.OBJECT_ID = fs.object_id
WHERE 
    t.NAME NOT LIKE 'dt%' 
    AND t.is_ms_shipped = 0
ORDER BY 
    t.Name