mediumOther

WRITE_COMPLETION Wait Type Explained

SQL Server WRITE_COMPLETION wait type indicates storage write latency. Learn diagnostic queries, fix scripts, and prevention strategies for this medium-severity wait.

Quick Answer

WRITE_COMPLETION waits occur when SQL Server threads are waiting for asynchronous write operations to complete, typically during checkpoint processes, lazy writer activity, or bulk operations. These waits indicate storage subsystem latency and become concerning when sustained above 10-15ms average or when paired with high PAGEIOLATCH waits.

Root Cause Analysis

WRITE_COMPLETION waits surface when SQL Server's asynchronous I/O subsystem has issued write requests to the storage layer but those operations have not yet completed. The SQL Server scheduler parks threads in this wait state while the Windows I/O completion port mechanism processes the outstanding writes.

This wait type primarily manifests during three scenarios: checkpoint operations flushing dirty pages from the buffer pool, lazy writer background processes cleaning buffers to maintain free page availability, and bulk operations like index rebuilds or large data modifications that generate significant write activity.

The buffer pool manager coordinates these writes through the I/O completion port architecture. When a thread requests a write operation, SQL Server issues an overlapped I/O request to Windows and immediately returns control to the scheduler. The thread enters WRITE_COMPLETION state until the I/O completion port signals that the storage subsystem has acknowledged the write.

Starting with SQL Server 2016, the introduction of multiple tempdb data files and improved checkpoint algorithms reduced some WRITE_COMPLETION pressure by distributing write workloads. SQL Server 2019's intelligent query processing and accelerated database recovery (ADR) further optimized write patterns, though ADR's persistent version store can introduce new write completion scenarios.

SQL Server 2022's buffer pool parallel scan improvements and enhanced checkpoint smoothing algorithms better distribute write operations across time, reducing write completion spikes. The integration with modern NVMe storage through improved I/O stack optimizations also reduces the frequency of prolonged WRITE_COMPLETION waits.

AutoDBA checks Storage latency monitoring, checkpoint configuration, and buffer pool optimization settings across your entire SQL Server instance in 60 seconds. Download the free diagnostic script and see what else needs attention.

Diagnostic Queries

-- Check current WRITE_COMPLETION wait statistics
SELECT 
    wait_type,
    waiting_tasks_count,
    wait_time_ms,
    max_wait_time_ms,
    signal_wait_time_ms,
    wait_time_ms - signal_wait_time_ms AS resource_wait_time_ms
FROM sys.dm_os_wait_stats 
WHERE wait_type = 'WRITE_COMPLETION'
ORDER BY wait_time_ms DESC;
-- Identify active write operations and their durations
SELECT 
    r.session_id,
    r.request_id,
    r.wait_type,
    r.wait_time,
    r.wait_resource,
    s.program_name,
    r.command,
    t.text
FROM sys.dm_exec_requests r
INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t
WHERE r.wait_type = 'WRITE_COMPLETION';
-- Analyze checkpoint and lazy writer performance metrics
SELECT 
    cntr_value AS checkpoint_pages_per_sec
FROM sys.dm_os_performance_counters 
WHERE counter_name = 'Checkpoint pages/sec'
UNION ALL
SELECT 
    cntr_value AS lazy_writes_per_sec
FROM sys.dm_os_performance_counters 
WHERE counter_name = 'Lazy writes/sec';
-- Check buffer pool pressure and dirty page ratios
SELECT 
    (SELECT COUNT(*) FROM sys.dm_os_buffer_descriptors WHERE is_modified = 1) AS dirty_pages,
    (SELECT COUNT(*) FROM sys.dm_os_buffer_descriptors) AS total_pages,
    CAST((SELECT COUNT(*) FROM sys.dm_os_buffer_descriptors WHERE is_modified = 1) * 100.0 / 
         (SELECT COUNT(*) FROM sys.dm_os_buffer_descriptors) AS DECIMAL(5,2)) AS dirty_page_percentage;
-- Monitor storage latency correlation with write completion
SELECT 
    database_id,
    file_id,
    num_of_writes,
    num_of_bytes_written,
    io_stall_write_ms,
    CASE WHEN num_of_writes > 0 
         THEN io_stall_write_ms / num_of_writes 
         ELSE 0 END AS avg_write_latency_ms
FROM sys.dm_io_virtual_file_stats(NULL, NULL)
WHERE num_of_writes > 0
ORDER BY avg_write_latency_ms DESC;

Fix Scripts

-- Optimize checkpoint frequency to reduce write completion spikes
-- This spreads checkpoint activity more evenly over time
USE master;
GO
-- WARNING: Test thoroughly in development first
-- Adjust recovery interval based on your RTO requirements
EXEC sp_configure 'recovery interval (min)', 5;  -- Default is 0 (auto)
RECONFIGURE WITH OVERRIDE;
-- Enable indirect checkpoint for better write distribution (SQL Server 2012+)
-- This provides more predictable checkpoint behavior
-- WARNING: Monitor transaction log usage after implementation
ALTER DATABASE [YourDatabase] 
SET TARGET_RECOVERY_TIME = 60 SECONDS;  -- Adjust based on requirements
-- Increase maximum server memory to reduce buffer pool pressure
-- This reduces lazy writer activity and associated write completion waits
-- WARNING: Leave adequate memory for OS and other applications
DECLARE @total_memory_gb INT = 64;  -- Replace with your server's total RAM
DECLARE @max_server_memory_mb INT = (@total_memory_gb - 4) * 1024;  -- Leave 4GB for OS

EXEC sp_configure 'max server memory (MB)', @max_server_memory_mb;
RECONFIGURE WITH OVERRIDE;
-- Add tempdb data files to distribute write load (if not already configured)
-- This reduces contention and write completion waits in tempdb
-- WARNING: Ensure adequate storage space before execution
USE master;
GO
DECLARE @logical_cpus INT = (SELECT cpu_count FROM sys.dm_os_sys_info);
DECLARE @current_files INT = (SELECT COUNT(*) FROM sys.master_files WHERE database_id = 2 AND type = 0);
DECLARE @files_to_add INT = @logical_cpus - @current_files;

WHILE @files_to_add > 0
BEGIN
    DECLARE @sql NVARCHAR(500) = 'ALTER DATABASE tempdb ADD FILE (NAME = tempdev' + CAST(@current_files + 1 AS VARCHAR(10)) + ', FILENAME = ''C:\TempDB\tempdev' + CAST(@current_files + 1 AS VARCHAR(10)) + '.mdf'', SIZE = 1024MB, FILEGROWTH = 256MB)';
    EXEC sp_executesql @sql;
    SET @current_files = @current_files + 1;
    SET @files_to_add = @files_to_add - 1;
END;

AutoDBA generates fix scripts like these automatically, with impact estimates and rollback SQL included.

Prevention

Configure appropriate recovery intervals and enable indirect checkpoint with TARGET_RECOVERY_TIME settings between 60-120 seconds to smooth checkpoint activity and reduce write completion spikes. This prevents the accumulation of dirty pages that create sudden write bursts.

Implement proper tempdb configuration with multiple data files equal to the number of logical processors up to 8, sized identically with appropriate growth settings. This distributes write operations across multiple files and reduces contention-related write completion waits.

Monitor storage subsystem performance using Windows Performance Monitor counters for disk queue length, write latency, and throughput. Establish baselines for average write latency under 10ms for traditional storage and under 2ms for NVMe. Configure alerts when write latencies exceed these thresholds consistently.

Size memory allocation appropriately, leaving buffer pool headroom to reduce lazy writer activity. Monitor dirty page ratios and maintain them below 10% during normal operations. Excessive dirty page percentages indicate insufficient memory or storage bottlenecks that will manifest as write completion waits.

Implement database maintenance windows for index rebuilds and statistics updates to prevent these write-intensive operations from interfering with normal transaction processing. Use online operations where possible and consider partitioned maintenance strategies for large databases.

Need hands-on help?

Dealing with persistent write_completion issues across your environment? Samix Technology provides hands-on SQL Server performance consulting with 15+ years of production DBA experience.

Related Pages