SQL Server Database Size Report for All Databases
Report Database Size in MB and GB for All SQL Server Databases
This script queries sys.master_files and sys.databases to report the total allocated size in megabytes and gigabytes for every user database on the SQL Server instance, sorted by largest database first.
Purpose and Overview
Knowing how large each database is — and tracking how that size changes over time — is a core part of SQL Server capacity planning. Running out of disk space is one of the most disruptive events a DBA can face: it halts log backups, prevents transactions from committing, and can take databases offline. This script, adapted from the DBA-Scripts collection by Bulent Gucuk, reads allocated file sizes from sys.master_files and joins to sys.databases to produce a single server-wide size report. It runs from the master database, requires no cross-database queries, and takes milliseconds to execute — making it safe to run at any time, including during a production incident.
Code Breakdown
The complete script is shown below, followed by an explanation of each section.
1USE master;
2GO
3SELECT
4 @@SERVERNAME AS server_name,
5 d.name AS database_name,
6 CAST(SUM(mf.size) AS BIGINT) * 8 / 1024 AS database_size_mb,
7 CAST(
8 CAST((CAST(SUM(mf.size) AS BIGINT) * 8 / 1024) AS NUMERIC(10, 2))
9 / 1024 AS NUMERIC(10, 2)
10 ) AS database_size_gb
11FROM sys.master_files AS mf
12INNER JOIN sys.databases AS d
13 ON d.database_id = mf.database_id
14WHERE d.database_id > 4 -- exclude system databases
15GROUP BY d.name
16ORDER BY database_size_gb DESC;
sys.master_files
sys.master_files is a catalog view in the master database that contains one row for every data and log file across all databases on the instance — including offline and detached databases that are still registered. The size column stores the current allocated file size in 8 KB pages. Multiplying by 8 converts pages to kilobytes; dividing by 1,024 converts kilobytes to megabytes.
Because sys.master_files is in master, this query works without switching database context or using cross-database references. All file sizes are visible from a single place.
Joining sys.databases
The INNER JOIN to sys.databases on database_id links each file row to its parent database and provides the database name. The filter WHERE d.database_id > 4 excludes the four system databases: master (1), tempdb (2), model (3), and msdb (4). Remove this filter if you want system databases included in the report.
Size Calculation
sys.master_files.size is in 8 KB pages. The conversion chain is:
1pages × 8 = kilobytes
2kilobytes / 1,024 = megabytes
3megabytes / 1,024 = gigabytes
The CAST(SUM(mf.size) AS BIGINT) prevents integer overflow on servers with very large databases where the page count exceeds the range of a standard INT. The outer CAST(... AS NUMERIC(10, 2)) produces a clean two-decimal-place gigabyte figure.
GROUP BY and Ordering
GROUP BY d.name aggregates all data and log files for each database into a single total. A database with multiple data files (such as a filegroup with several NDF files) and a log file (LDF) will have multiple rows in sys.master_files — the GROUP BY sums them all. ORDER BY database_size_gb DESC puts the largest databases at the top, which is where attention should focus first during capacity planning.
Key Benefits and Use Cases
- Instant server-wide storage snapshot with no cross-database queries
- Works from a single connection to master — no looping through databases required
- Sorts largest databases first for immediate capacity focus
- Safe to run at any time including production incidents — reads only catalog metadata
- Serves as a baseline for tracking database growth trends when run regularly
@@SERVERNAMEin the output makes results identifiable when aggregating across multiple instances
Performance Considerations
- Allocated vs. used space:
sys.master_files.sizereflects the space currently allocated to the file on disk — not the space actually used by data. A 100 GB data file with 30 GB of actual data will still report as 100 GB. To report used space, querysys.dm_db_file_space_usageper database or useDBCC SQLPERF('LOGSPACE')for log files. - Auto-growth events: The allocated size grows with auto-growth events and shrinks only when files are explicitly shrunk. A database that had a large import and then deleted the data will still show the full pre-import allocated size.
- tempdb: tempdb is excluded by the
database_id > 4filter. If you need to monitor tempdb size separately, querysys.master_files WHERE database_id = 2directly, or include it by removing the filter. - Availability Groups: On an Availability Group secondary,
sys.master_filesshows the secondary replica's file sizes, which may differ slightly from the primary if auto-growth has occurred on one but not the other.
Practical Tips
To also show the number of data files and log files per database, extend the GROUP BY with a CASE expression:
1SELECT
2 d.name AS database_name,
3 SUM(CASE WHEN mf.type = 0 THEN 1 ELSE 0 END) AS data_file_count,
4 SUM(CASE WHEN mf.type = 1 THEN 1 ELSE 0 END) AS log_file_count,
5 CAST(SUM(mf.size) AS BIGINT) * 8 / 1024 AS total_size_mb,
6 CAST(CAST((CAST(SUM(mf.size) AS BIGINT) * 8 / 1024)
7 AS NUMERIC(10, 2)) / 1024 AS NUMERIC(10, 2)) AS total_size_gb
8FROM sys.master_files AS mf
9INNER JOIN sys.databases AS d ON d.database_id = mf.database_id
10WHERE d.database_id > 4
11GROUP BY d.name
12ORDER BY total_size_gb DESC;
mf.type = 0 identifies data files (MDF and NDF); mf.type = 1 identifies log files (LDF).
For a visual size comparison using proportional bars — useful in a quick console report — this alternative from the sqlserver-kit community collection shows each database as a percentage of total instance storage:
1SELECT
2 DB_NAME(database_id) AS database_name,
3 CAST(SUM(size) * 8.0 / 1024 / 1024 AS DECIMAL(30, 2)) AS total_size_gb,
4 CAST(
5 (SUM(size) / (SELECT SUM(CONVERT(DECIMAL(30, 4), size))
6 FROM sys.master_files WITH (NOWAIT))) * 100.00
7 AS DECIMAL(10, 2)) AS pct_of_instance,
8 REPLICATE('|',
9 CONVERT(INT,
10 (SUM(size) / (SELECT SUM(CONVERT(DECIMAL(30, 2), size))
11 FROM sys.master_files WITH (NOWAIT))) * 100
12 )
13 ) AS size_graph
14FROM sys.master_files WITH (NOWAIT)
15GROUP BY database_id
16ORDER BY total_size_gb DESC;
Schedule the main script as a daily SQL Server Agent job that inserts results into a history table. Querying that table over time shows monthly growth rates per database, which feeds directly into capacity planning conversations with infrastructure teams.
Conclusion
This script gives DBAs a fast, reliable view of database storage allocation across the entire SQL Server instance. Reading directly from sys.master_files in master means no looping, no dynamic SQL, and no cross-database permission issues. The MB and GB columns make the output immediately useful for capacity planning, and sorting by size descending puts the most important databases first. Add the data file and log file counts, schedule it as a daily job, and store historical results to build a storage growth trend report that requires no third-party tooling.
References
- DBA-Scripts on GitHub by Bulent Gucuk — Source repository containing the database size script adapted for this article
- sqlserver-kit on GitHub by Konstantin Taranov — Source for the proportional graph alternative query shown in Practical Tips
- Microsoft Docs: sys.master_files — Full column reference for the catalog view containing all database file metadata
- Microsoft Docs: sys.databases — Reference for the catalog view that holds all database-level properties and settings