Sandir

/*
Description:

This procedure gets current table and index sizes of particular database and stores it to tables.

*/

BEGIN

SET NOCOUNT ON;

DROP TABLE IF EXISTS #AllTablesIndexes;
DROP TABLE IF EXISTS #AllTables;
DROP TABLE IF EXISTS #AllIndexes;

DECLARE @DatabaseName sysname =
'DWH';

DECLARE @TableName sysname =
'';

DECLARE @SchemaName sysname =
'';

DECLARE @TableMatch AS bit =
0;



IF @TableMatch = 0
BEGIN
SET @TableName = CONCAT(N'%', @TableName, N'%')
END;



DECLARE @NewDatabaseName sysname = CONCAT('''',@DatabaseName, '''');
DECLARE @NewTableName sysname = CONCAT('''',@TableName, '''');
DECLARE @NewSchemaName sysname = CONCAT('''',@SchemaName, '''');

DECLARE @SQL nvarchar(2000);



CREATE TABLE #AllTablesIndexes (
[DBID] int NOT NULL,
[DBname] nvarchar(128) NOT NULL,
[TableName] nvarchar(128) NOT NULL,
[TableID] int NOT NULL,
[FullTableName] nvarchar(386) NOT NULL,
[IndexName] nvarchar(128),
[IndexType] nvarchar(60) NOT NULL,
[IndexSubType] nvarchar(60) NOT NULL,
[Rows] bigint NOT NULL,
[TotalPages] bigint NOT NULL,
[UsedPages] bigint NOT NULL,
[UnusedPages] bigint NOT NULL,
[CreateDateTime] datetime2(3),
[ModifyDateTime] datetime2(3)
);


SET @SQL =
CONCAT('USE [?];
SELECT
DB_ID (DB_NAME()) AS [DBID],
DB_NAME() AS [DBname],
t.[name] AS [TableName],
t.[object_id] AS [TableID],
CONCAT(N''['',DB_NAME(),N''].'', N''['', s.[name], N''].'', N''['', t.[name], N'']'') AS [FullTableName],
i.[name] AS IndexName,
CASE
WHEN i.index_id = 0 THEN ''HEAP''
WHEN i.index_id = 1 THEN ''CLUSTERED''
WHEN i.index_id > 1 THEN ''NONCLUSTERED''
END AS [IndexType],
CASE
WHEN i.type = 0 THEN ''HEAP''
WHEN i.type = 1 THEN ''ROWSTORE''
WHEN i.type = 2 THEN ''ROWSTORE''
WHEN i.type = 3 THEN ''XML''
WHEN i.type = 4 THEN ''Spatial''
WHEN i.type = 5 THEN ''COLUMNSTORE''
WHEN i.type = 6 THEN ''COLUMNSTORE''
WHEN i.type = 7 THEN ''HASH''
END AS [IndexSubType],
p.[Rows],
SUM(a.total_pages) AS TotalPages,
SUM(a.used_pages) AS UsedPages,
SUM(a.total_pages) - SUM(a.used_pages) AS UnusedPages,
t.create_date AS CreateDate,
t.modify_date AS ModifyDate
FROM sys.tables AS t WITH(NOLOCK)
INNER JOIN sys.schemas AS s WITH(NOLOCK) ON t.schema_id = s.schema_id
INNER JOIN sys.indexes AS i WITH(NOLOCK) ON t.object_id = i.object_id
INNER JOIN sys.partitions AS p WITH(NOLOCK) ON i.object_id = p.object_id AND i.index_id = p.index_id
INNER JOIN sys.allocation_units AS a WITH(NOLOCK) ON p.partition_id = a.container_id
WHERE 1=1
AND (ISNULL(', @NewDatabaseName,', '''') = '''' OR DB_NAME() = ',@NewDatabaseName,')
AND (ISNULL(',@NewTableName,', '''') = '''' OR t.[Name] LIKE ',@NewTableName,')
AND (ISNULL(', @NewSchemaName, ', '''') = '''' OR s.[Name] LIKE ', @NewSchemaName, ')
GROUP BY
t.[name],
t.[object_id],
CONCAT(N''['',DB_NAME(),N''].'', N''['', s.[name], N''].'', N''['', t.[name], N'']''),
i.[name],
i.index_id,
i.type,
p.[Rows],
t.create_date,
t.modify_date');

INSERT INTO #AllTablesIndexes
EXEC sp_msforeachdb @SQL -- max 2000 size :(


SELECT
[DBID]
,[DBname]
,[TableName]
,[TableID]
,[FullTableName]
,[IndexName]
,[IndexType]
,[IndexSubType],

SUM([rows]) AS [RowCount],
SUM(TotalPages) AS [TotalPages],
SUM(UsedPages) AS [UsedPages],
SUM(TotalPages) - SUM(UsedPages) AS [UnusedPages],

CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0)) AS [TotalSpace_MB],
CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0)) AS [UsedSpace_MB],
CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0)) - CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0)) AS [UnusedSpace_MB],
-- show
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM([rows]) ), 1), '.00', '') AS [RowCount_show],

REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM(TotalPages)), 1), '.00', '') AS [TotalPages_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM(UsedPages)), 1), '.00', '') AS [UsedPages_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM(TotalPages) - SUM(UsedPages)), 1), '.00', '') AS [UnusedPages_show],

REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0))), 1), '.00', '') AS [TotalSpace_MB_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0))), 1), '.00', '') AS [UsedSpace_MB_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0)) - CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0))), 1), '.00', '') AS [UnusedSpace_MB_show],
[CreateDateTime],
[ModifyDateTime]
INTO #AllTables
FROM #AllTablesIndexes
WHERE 1=1
AND [IndexType] IN ('HEAP', 'CLUSTERED') -- only tables
GROUP BY
[DBID]
,[DBname]
,[TableName]
,[TableID]
,[FullTableName]
,[IndexName]
,[IndexType]
,[IndexSubType]
,[CreateDateTime]
,[ModifyDateTime]



SELECT
[DBID]
,[DBname]
,[TableName]
,[TableID]
,[FullTableName]
,[IndexName]
,[IndexType]
,[IndexSubType],

SUM([rows]) AS [RowCount],

SUM(TotalPages) AS [TotalPages],
SUM(UsedPages) AS [UsedPages],
SUM(TotalPages) - SUM(UsedPages) AS [UnusedPages],

CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0)) AS [TotalSpace_MB],
CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0)) AS [UsedSpace_MB],
CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0)) - CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0)) AS [UnusedSpace_MB],
-- show
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM([rows]) ), 1), '.00', '') AS [RowCount_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM(TotalPages)), 1), '.00', '') AS [TotalPages_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM(UsedPages)), 1), '.00', '') AS [UsedPages_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, SUM(TotalPages) - SUM(UsedPages)), 1), '.00', '') AS [UnusedPages_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0))), 1), '.00', '') AS [TotalSpace_MB_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0))), 1), '.00', '') AS [UsedSpace_MB_show],
REPLACE(CONVERT(VARCHAR, CONVERT(MONEY, CAST((SUM(TotalPages) * 8) / 1024.00 as decimal(18,0)) - CAST((SUM(UsedPages) * 8) / 1024.00 as decimal(18,0))), 1), '.00', '') AS [UnusedSpace_MB_show],
[CreateDateTime],
[ModifyDateTime]
INTO #AllIndexes
FROM #AllTablesIndexes
WHERE 1=1
AND [IndexType] IN ('NONCLUSTERED', 'CLUSTERED') -- only tables
GROUP BY
[DBID]
,[DBname]
,[TableName]
,[TableID]
,[FullTableName]
,[IndexName]
,[IndexType]
,[IndexSubType]
,[CreateDateTime]
,[ModifyDateTime]

INSERT INTO [maint].[tTableSizes]
SELECT
'TblStats' AS TableStats,
[DBname],
[TableName],
[FullTableName],
[IndexType],
[IndexSubType],
[RowCount],
[TotalPages],
[UsedPages],
[UnusedPages],
[TotalSpace_MB],
[UsedSpace_MB],
[UnusedSpace_MB],
CAST(GETDATE() AS date) AS SnapshotDate
FROM #AllTables
ORDER BY TotalSpace_MB desc

INSERT INTO [maint].[tIndexSizes]
SELECT
'IndexStats' AS IndexStats,
[DBname],
[FullTableName],
[IndexName],
[IndexType],
[IndexSubType],
[RowCount],
[TotalPages],
[UsedPages],
[UnusedPages],
[TotalSpace_MB],
[UsedSpace_MB],
[UnusedSpace_MB],
CAST(GETDATE() AS date) AS SnapshotDate
FROM #AllIndexes
WHERE 1=1
AND [IndexType] IN ('NONCLUSTERED') -- only NONCLUSTERED indexes
ORDER BY TotalSpace_MB desc

END

Blogs

Methodology for dealing with bad data in production

By

Pinal Dave wrote up his methodology for what to do when you discover bad...

How to Provision an Azure SQL Database

By

Aside from spinning up a SQL Server instance container, the free Azure SQL Database...

Claude finds two cryptographic weaknesses (but the sky isn’t falling)

By

If you haven't seen the announcement, Anthropic was able to utilize Claude (Mythos Preview)...

Read the latest Blogs

Forums

Why SQL Server Database Attach fails and how to repair it

By Nisarg Upadhyay

Comments posted to this topic are about the item Why SQL Server Database Attach...

Fixing P1 Queries

By Steve Jones - SSC Editor

Comments posted to this topic are about the item Fixing P1 Queries

BIT_COUNT() IV

By Steve Jones - SSC Editor

Comments posted to this topic are about the item BIT_COUNT() IV

Visit the forum

Question of the Day

BIT_COUNT() IV

In SQL Server 2025, I run this code:

select bit_count('A')
What is returned?

See possible answers