SQL Optima guide
Autogrowth events are silent outages
Instant file growth can stall sessions without a flashy alert.
/*
================================================================================
Database File Space, Autogrowth, and Utilization
================================================================================
Description:
Reports current file size, space used, free space, and autogrowth settings
for all data and log files across user databases. Identifies files that are
near capacity or have suboptimal autogrowth configurations.
Output:
File-level details including used space percentage, autogrowth increments,
and a status column indicating files that need attention.
Action:
For files with UsedPct > 90%, extend the file size immediately:
ALTER DATABASE [DBName] MODIFY FILE (NAME = logical_name, SIZE = new_size_MB);
For files with percentage-based autogrowth ("BY_PERCENT"), switch to fixed-MB
growth to prevent uncontrolled growth events:
ALTER DATABASE [DBName] MODIFY FILE (NAME = logical_name, FILEGROWTH = 1024MB);
Monitor log files closely — logs that grow unexpectedly may indicate
long-running transactions or missing log backups.
Parameters:
@DatabaseList - comma-separated database names or NULL for all user DBs
@StalePctThreshold - used space % threshold for warnings (default 80)
Criticality: High
Author: Ravi Sharma
================================================================================
*/
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET NOCOUNT ON;
DECLARE @DatabaseList NVARCHAR(MAX) = NULL; -- e.g. N'userdb'
DECLARE @StalePctThreshold DECIMAL(5,2) = 80.0;
IF OBJECT_ID(N'tempdb..#FileSpaceStats') IS NOT NULL DROP TABLE #FileSpaceStats;
CREATE TABLE #FileSpaceStats (
DatabaseName SYSNAME,
LogicalName SYSNAME,
PhysicalName NVARCHAR(260),
FileType VARCHAR(10),
TotalSizeMB DECIMAL(18,2),
SpaceUsedMB DECIMAL(18,2),
FreeSpaceMB DECIMAL(18,2),
AutogrowthSetting VARCHAR(50),
UsedPct DECIMAL(5,2),
SpaceStatus VARCHAR(20)
);
IF OBJECT_ID(N'tempdb..#DbTargets') IS NOT NULL DROP TABLE #DbTargets;
CREATE TABLE #DbTargets (database_name SYSNAME NOT NULL PRIMARY KEY);
IF @DatabaseList IS NOT NULL AND LTRIM(RTRIM(@DatabaseList)) <> N''
BEGIN
INSERT INTO #DbTargets (database_name)
SELECT LTRIM(RTRIM(value))
FROM STRING_SPLIT(@DatabaseList, N',')
WHERE LTRIM(RTRIM(value)) <> N'';
END
ELSE
BEGIN
INSERT INTO #DbTargets (database_name)
SELECT name FROM sys.databases WHERE database_id > 4 AND state = 0 AND is_in_standby = 0;
END;
DECLARE @db_name SYSNAME;
DECLARE @SQL NVARCHAR(MAX);
DECLARE db_cursor CURSOR LOCAL FAST_FORWARD FOR
SELECT database_name FROM #DbTargets ORDER BY database_name;
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO @db_name;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = N'USE ' + QUOTENAME(@db_name) + N';
INSERT INTO #FileSpaceStats
SELECT
DB_NAME(),
df.name,
df.physical_name,
df.type_desc,
CAST(df.size * 8.0 / 1024 AS DECIMAL(18,2)),
CAST(FILEPROPERTY(df.name, N''SpaceUsed'') * 8.0 / 1024 AS DECIMAL(18,2)),
CAST((df.size - FILEPROPERTY(df.name, N''SpaceUsed'')) * 8.0 / 1024 AS DECIMAL(18,2)),
CASE WHEN df.is_percent_growth = 1 THEN CAST(df.growth AS VARCHAR(10)) + N''%'' ELSE CAST(df.growth * 8 / 1024 AS VARCHAR(10)) + N'' MB'' END,
CAST(FILEPROPERTY(df.name, N''SpaceUsed'') * 100.0 / NULLIF(df.size, 0) AS DECIMAL(5,2)),
CASE
WHEN CAST(FILEPROPERTY(df.name, N''SpaceUsed'') * 100.0 / NULLIF(df.size, 0) AS DECIMAL(5,2)) >= ' + CAST(@StalePctThreshold AS NVARCHAR(10)) + N' THEN N''WARNING''
ELSE N''OK''
END
FROM sys.database_files AS df;';
BEGIN TRY
EXEC sys.sp_executesql @SQL;
END TRY
BEGIN CATCH
INSERT INTO #FileSpaceStats
VALUES (@db_name, N'ERROR', LEFT(ERROR_MESSAGE(), 260), N'N/A', 0, 0, 0, N'N/A', 0, N'ERROR');
END CATCH;
FETCH NEXT FROM db_cursor INTO @db_name;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
SELECT
N'Database File Growth' AS [Result_Set],
[DatabaseName] AS [Database_Name],
[LogicalName] AS [Logical_Name],
[PhysicalName] AS [Physical_Name],
[FileType] AS [File_Type],
[TotalSizeMB] AS [Total_Size_MB],
[SpaceUsedMB] AS [Space_Used_MB],
[FreeSpaceMB] AS [Free_Space_MB],
[AutogrowthSetting] AS [Autogrowth_Setting],
[UsedPct] AS [Used_Pct],
[SpaceStatus] AS [Space_Status]
FROM #FileSpaceStats
ORDER BY [UsedPct] DESC, [TotalSizeMB] DESC;
DROP TABLE #FileSpaceStats;
DROP TABLE #DbTargets;
Review the full script and confirm the connected SQL Server instance before execution. The run instructions and output guide appear later in this article.
Autogrowth is a safety net, not a capacity plan.
If growth events cluster during business hours, pre-size files and fix the workload that forces sudden expansion. Monitoring should surface growth cadence next to latency spikes.
Why file growth deserves a method
The central principle is that autogrowth is an emergency safety mechanism, not a capacity-management strategy. A single metric, recommendation, or successful command is not enough. The decision has to connect an observed symptom to a plausible cause, a controlled change, and a result that can be verified under the workload that matters.
Evidence to collect
Use evidence from the same time window whenever possible:
- growth events and duration
- free space in data and log files
- underlying volume capacity and latency
- log reuse waits and transaction behavior
A practical workflow
- Baseline file size and growth history.
- Choose fixed growth increments.
- Pre-size files for the forecast workload.
- Alert before both database and volume space become critical.
Common mistakes
Avoid these shortcuts:
- percentage-based growth
- tiny growth increments
- monitoring the file but not its volume
Verification and completion
Define completion before making the change. Confirm correctness first, then compare latency, throughput, reads, CPU, waits, storage behavior, or recovery time as appropriate for Autogrowth events are silent outages. Test negative and boundary cases, not only the path expected to succeed. Watch the system long enough to cover the relevant workload pattern.
Download and run the diagnostic
Database file growth and utilization
Download database_files_growth.sqlBefore you run it
- Run the script first on a non-production or read-only connection when possible.
- Review the complete SQL file before execution and confirm that the connected instance is the intended target.
- Required access: VIEW SERVER STATE plus visibility into the target databases.
- Open SQL Server Management Studio or Azure Data Studio, connect to the instance, open the downloaded file, and select Execute. Do not run diagnostic scripts through an application login.
- Save the result grid with the server name, collection time, and incident window. DMV output changes over time and often resets after a SQL Server restart.
What the script does
Inventories data and log files, allocated and used space, free space, growth settings, and warning status across selected user databases. The download is intended for diagnosis and does not apply an automatic remediation. Read every statement anyway, especially when adapting the script for automation or a different SQL Server version.
How to read the output
Prioritize warning rows with high UsedPct and low FreeSpaceMB. Review PhysicalName to confirm that the hosting volume also has space. Percentage growth and very small fixed increments deserve review because they can create increasingly large pauses or repeated growth events.