Reputation: 9781
How can you tell what Tables are taking up the most space in a SQL Server 2005 Database?
I am sure there is some System Stored Procedure that shows this information.
I have a TEST database that grew from 1tb to 23tb. We are currently doing a lot of client conversion testing in the database, which entails running the same conversion Stored Procedure multiple times. It does DELETEs which I am sure is increasing the Transaction Log. But this got me thinking to ask this question.
the big problem is the dbo.Download table, it creates massive storage that is actually not needed, I had 3GB before truncating it, then 52MB ;)
Upvotes: 112
Views: 119743
Reputation: 27385
SELECT a.name AS ObjectName,
SUM(reserved_page_count) * 8.0 / 1024 AS Size_in_MB
FROM sys.dm_db_partition_stats AS ps
INNER JOIN sys.sysobjects AS a
ON ps.object_id = a.id
GROUP BY a.name ;
Upvotes: 0
Reputation: 4345
Thanks to @marc_s for the answer. I needed to know data vs index space so I went ahead and expanded on the query to include that.
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
Upvotes: 7
Reputation: 681
Rossisdead's comment answered this question the best for me, I wish it wasn't buried in a comment. This will be useful for people like me not trying to script the solution (the OP did not ask for a code snippet)
If you're using Management Studio you can also right click on the database and go to Reports -> Disk Usage by Table for the same results
Upvotes: 12
Reputation: 43984
Use sp_spacedUsed
Exec sp_spaceused N'YourTableName'
Or if you want to execute the sp_spaceused
for each table in your database then you can use this 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
The above SQL is from here
Upvotes: 37
Reputation: 754488
Try this script - it will list the number of rows and the space used by data rows (and the total space used) for all tables in your database:
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)
Upvotes: 251