====== Summarise space usage ======
{{tag> space disk housekeeping}}
===== By table =====
SELECT
QUOTENAME(OBJECT_SCHEMA_NAME(p.[object_id])) + '.' + QUOTENAME(OBJECT_NAME(p.[object_id])) AS TableName
, SUM(IIF(a.[type] = 1, p.[rows], 0)) AS [TableRows]
, SUM(a.used_pages) AS UsedPages
, IIF(SUM(a.used_pages) = 0, SUM(IIF(a.[type] = 1, p.[rows], 0)),
SUM(IIF(a.[type] = 1, p.[rows], 0)) / SUM(a.used_pages)) AS RowsPerPage
, SUM(a.total_pages) AS TotalPages
, SUM(a.total_pages) * 8 / 1024 AS TotalSpaceMB
, MAX(p.[data_compression_desc]) AS CompressionType
FROM sys.partitions p
INNER JOIN sys.allocation_units a ON p.[partition_id] = a.container_id
WHERE p.index_id <= 1
-- 0 = heap, 1 = clustered -- table will have index with index_id of 0 *or* 1, not both
GROUP BY p.[object_id]
ORDER BY TotalSpaceMB DESC
==== sp_spaceused ====
This script calls ''sp_spaceused'' for every table or indexed view in the database. I don't like it much but that's just my preference.
-- declare table variable to hold list of tables & indexed views
DECLARE @tables TABLE (
SchemaName VARCHAR(128)
, TableName VARCHAR(128)
, ObjectId INT
, Reported BIT DEFAULT 0
)
-- collect list of tables & indexed views
INSERT INTO @tables (
SchemaName
, TableName
, ObjectId
)
SELECT DISTINCT
s.name
, o.name
, o.object_id
FROM sys.schemas s
INNER JOIN sys.objects o ON o.schema_id = s.schema_id
LEFT JOIN sys.indexes i ON i.object_id = o.object_id
WHERE o.type = 'U'
OR (o.type = 'V' AND i.index_id IS NOT NULL)
-- declare table variable to hold sp_spaceused results
DECLARE @objId INT
DECLARE @sql VARCHAR(MAX)
DECLARE @results TABLE (
SchemaName VARCHAR(128)
, TableName VARCHAR(128)
, TableRows CHAR(11)
, DataSize VARCHAR(18)
, IndexSize VARCHAR(18)
, ReservedSpace VARCHAR(18)
, UnusedSpace VARCHAR(18)
)
-- call sp_spaceused for each table in @tables and cache results
WHILE 1 = 1
BEGIN
SET @objId = NULL
SELECT TOP 1
@objId = ObjectId
FROM @tables
WHERE Reported = 0
IF @objId IS NULL
BREAK
SELECT
@sql = 'sp_spaceused @objname = ''[' + SchemaName + '].[' + TableName + ']'''
FROM @tables
WHERE ObjectId = @objId
INSERT INTO @results (
TableName
, TableRows
, ReservedSpace
, DataSize
, IndexSize
, UnusedSpace
)
EXEC (@sql)
UPDATE r
SET r.SchemaName = t.SchemaName
FROM @results r
INNER JOIN @tables t ON t.ObjectId = @objId
WHERE r.SchemaName IS NULL
UPDATE @tables
SET Reported = 1
WHERE ObjectId = @objId
END
-- inspect cached results
SELECT
SchemaName
, TableName
, CAST(TableRows AS INT) AS TableRows
, ROUND(CAST(REPLACE(DataSize, 'KB', '') AS FLOAT)/1024, 1) AS DataMb
, ROUND(CAST(REPLACE(IndexSize, 'KB', '') AS FLOAT)/1024, 1) AS IndexMb
, ROUND(CAST(REPLACE(UnusedSpace, 'KB', '') AS FLOAT)/1024, 1) AS UnusedMb
, ROUND(CAST(REPLACE(ReservedSpace, 'KB', '') AS FLOAT)/1024, 1) AS ReservedMb
FROM @results
ORDER BY 4 DESC
===== By database =====
WITH files AS (
SELECT
database_id
, CAST(size*8 AS FLOAT)/1024 AS size -- size in MB
, type_desc
FROM sys.master_files
), dbs AS (
SELECT
database_id
, ROUND(SUM(size),1) AS TotalMB
, ROUND(SUM(CASE type_desc WHEN 'ROWS' THEN size ELSE 0 END),1) AS DataMB
, ROUND(SUM(CASE type_desc WHEN 'LOG' THEN size ELSE 0 END),1) AS LogsMB
, ROUND(SUM(CASE WHEN type_desc NOT IN ('ROWS', 'LOG') THEN size ELSE 0 END),1) AS OtherMB
FROM files
GROUP BY database_id
)
-- SELECT SUM(TotalMB) FROM dbs
SELECT
db.name AS DbName
, db.recovery_model_desc
, db.is_auto_shrink_on
, dbs.*
FROM sys.databases db
INNER JOIN dbs ON dbs.database_id = db.database_id
ORDER BY TotalMB DESC