Home > Database Technology > Table Disk Space Usage By Filegroup and Partition

Table Disk Space Usage By Filegroup and Partition

I wanted a more granular level of detail when looking at disk space usage of our databases. I wanted to see the disk usage of each table. Since we use partitioning pretty heavily I also wanted to see how that usage was broken out by partition and filegroup. In our implementation we have a separate filegroup for each table partition but in a configuration that has multiple parititons on a partition this script can tell you usage for either metric.

 

Normally I’ll take this query and take the results over to excel and pivot the data so that I can filter and sum data in whatever way I want. I also have this running in a SQL Agent job and inserting into a table so that I connect to that table and do growth trend analysis.

 

Note: I’ve commented out the last line of the WHERE clause in this script to show both data and index stats. If you uncomment that line you will see just Data usage. If you don’t uncomment that line you’ll have to remember to filter your results by the “Type” column so that you don’t duplicate your storage statistics.

 

Here’s a quick explanation of the data columns I’m pulling in.
By default data pages in MSSQL are 8KB and that’s the assumption that I’m making with this query.

 

  • Used_Pages: the number of pages actually used by the table including non-leaf B-tree pages and IAM pages.
  • Reserved_Pages: is the number of pages being reserved in total for the object, whether used or not.
  • Data_Pages: the number of pages being used excluding non-leaf B-tree pages.

 

here’s a link to the BOL page that describes these: http://msdn.microsoft.com/en-us/library/ms187737.aspx

SELECT
	DB_NAME() AS 'DatabaseName'
	,OBJECT_NAME(p.OBJECT_ID) AS 'TableName'
	,p.index_id AS 'IndexId'
	,CASE
		WHEN p.index_id = 0 THEN 'HEAP'
		ELSE i.name
	END AS 'IndexName'
	,p.partition_number AS 'PartitionNumber'
	,prv_left.value AS 'LowerBoundary'
	,prv_right.value AS 'UpperBoundary'
	,CASE
		WHEN fg.name IS NULL THEN ds.name
		ELSE fg.name
	END AS 'FileGroupName'
	,CAST(p.used_page_count * 0.0078125 AS NUMERIC(18,2)) AS 'UsedPages_MB'
	,CAST(p.in_row_data_page_count * 0.0078125 AS NUMERIC(18,2)) AS 'DataPages_MB'
	,CAST(p.reserved_page_count * 0.0078125 AS NUMERIC(18,2)) AS 'ReservedPages_MB'
	,CASE
		WHEN p.index_id IN (0,1) THEN p.row_count
		ELSE 0
	END AS 'RowCount'
	,CASE
		WHEN p.index_id IN (0,1) THEN 'data'
		ELSE 'index'
	END 'Type'
FROM sys.dm_db_partition_stats p
	INNER JOIN sys.indexes i
		ON i.OBJECT_ID = p.OBJECT_ID AND i.index_id = p.index_id
	INNER JOIN sys.data_spaces ds
		ON ds.data_space_id = i.data_space_id
	LEFT OUTER JOIN sys.partition_schemes ps
		ON ps.data_space_id = i.data_space_id
	LEFT OUTER JOIN sys.destination_data_spaces dds
		ON dds.partition_scheme_id = ps.data_space_id
		AND dds.destination_id = p.partition_number
	LEFT OUTER JOIN sys.filegroups fg
		ON fg.data_space_id = dds.data_space_id
	LEFT OUTER JOIN sys.partition_range_values prv_right
		ON prv_right.function_id = ps.function_id
		AND prv_right.boundary_id = p.partition_number
	LEFT OUTER JOIN sys.partition_range_values prv_left
		ON prv_left.function_id = ps.function_id
		AND prv_left.boundary_id = p.partition_number - 1
WHERE
	OBJECTPROPERTY(p.OBJECT_ID, 'ISMSSHipped') = 0
	--AND p.index_id in (0,1)
  1. Troy Holland
    August 13th, 2009 at 22:11 | #1

    Thanks a million! This is exactly what I was looking for.

  2. Ray Tomlinson
    August 23rd, 2009 at 05:00 | #2

    Yes, thanks from me too!
    Just finished the section on Partitions in the MOC training and realised as I worked through the exercises that nothing was stated about how to retrieve a not insignificant piece of info… The link between a file group and it’s associated partion\s

  3. September 1st, 2009 at 03:09 | #3

    Tnx!

  1. No trackbacks yet.