- SELECT COUNT(*) FROM MyTable;
This method has some disadvantages:
- We can only get a rows count, but not a physical size of table
- This query works on one table, name of which we have to define explicitly
- If table has no PRIMARY KEY, then this query can be very slow
There is some other method - to use a statistic from system tables.
This method uses for example this predefined SSMS report:

We can start Profiler (Menu =&rt; Tools =&rt; SQL Server Profiler) and extract for own usage a background query of this report.
I have already extracted this query and reformated as standalone VIEW:
- CREATE VIEW dbo.disk_usage_by_table
- AS
- SELECT TOP(100) PERCENT
- Database_Name = DB_NAME(),
- Schema_Name = CAST(a3.name AS SYSNAME),
- Table_Name = CAST(a2.name AS SYSNAME),
- Records = a1.records,
- Reserved_KB = (a1.reserved + ISNULL(a4.reserved,0))* 8,
- Data_KB = a1.data * 8,
- Indexes_KB = CASE
- WHEN (a1.used + ISNULL(a4.used,0)) > a1.data
- THEN (a1.used + ISNULL(a4.used,0)) - a1.data
- ELSE 0
- END * 8,
- Unused_KB = CASE
- WHEN (a1.reserved + ISNULL(a4.reserved,0)) > a1.used
- THEN (a1.reserved + ISNULL(a4.reserved,0)) - a1.used
- ELSE 0
- END * 8
- FROM
- (
- SELECT
- ps.object_id,
- records = SUM(
- CASE
- WHEN (ps.index_id < 2)
- THEN row_count
- ELSE 0
- END
- ),
- reserved = SUM(ps.reserved_page_count),
- data = SUM(
- CASE
- WHEN ps.index_id < 2
- THEN ps.in_row_data_page_count
- + ps.lob_used_page_count
- + ps.row_overflow_used_page_count
- ELSE ps.lob_used_page_count
- + ps.row_overflow_used_page_count
- END
- ),
- used = SUM(ps.used_page_count)
- FROM sys.dm_db_partition_stats ps
- GROUP BY ps.object_id
- ) AS a1
- INNER JOIN sys.all_objects a2 ON ( a1.object_id = a2.object_id )
- INNER JOIN sys.schemas a3 ON (a2.schema_id = a3.schema_id)
- LEFT OUTER JOIN (
- SELECT
- it.parent_id,
- SUM(ps.reserved_page_count) AS reserved,
- SUM(ps.used_page_count) AS used
- FROM sys.dm_db_partition_stats ps
- INNER JOIN sys.internal_tables it ON (it.object_id = ps.object_id)
- WHERE it.internal_type IN (202,204)
- GROUP BY it.parent_id
- ) AS a4 ON (a4.parent_id = a1.object_id)
- WHERE a2.type <> N'S' and a2.type <> N'IT'
- ORDER BY Table_Name;
If we query this VIEW:
- SELECT * FROM dbo.disk_usage_by_table;
then we can see that [count rows], [reserved space], [space used for data], [space used for indexes] and [free space] for 106 tables takes less then 1 second:

We can also filter or join this view with other tables/views:
- SELECT Records FROM dbo.disk_usage_by_table WHERE Table_Name = 'dim_date';

This method has folowing advantages:
- Is very very fast
- Is independent of table names
- Shows
- Count of records
- Reserved space (in KBytes)
- Space used by data (in KBytes)
- Space used by indexes (in KBytes)
- Unused space (in KBytes)
You can use this metod for example in ETL processes to count (outside of transformation) rows and space before and after load.
No comments:
Post a Comment
Note: only a member of this blog may post a comment.