SQL Server VLF Details: Count, Size and Log Reuse Wait

VLF detail per database: count, active VLFs, log size, average VLF size and what is stopping log reuse. Uses sys.dm_db_log_info (SQL Server 2016 SP2 and later). The fix for a high count is at the bottom.

-- VLF detail per database (SQL Server 2016 SP2 and later)
-- Shows how many VLFs there are, how many are active, the log size and the average VLF size.
SELECT d.name                                                      AS DatabaseName,
       d.recovery_model_desc                                       AS RecoveryModel,
       d.log_reuse_wait_desc                                       AS LogReuseWait,
       COUNT(*)                                                    AS VLFCount,
       SUM(CASE WHEN li.vlf_active = 1 THEN 1 ELSE 0 END)          AS ActiveVLFs,
       CAST(SUM(li.vlf_size_mb) AS decimal(18, 2))                 AS LogSizeMB,
       CAST(AVG(li.vlf_size_mb) AS decimal(18, 2))                 AS AvgVLFSizeMB
FROM sys.databases AS d
CROSS APPLY sys.dm_db_log_info(d.database_id) AS li
WHERE d.state_desc = 'ONLINE'
GROUP BY d.name, d.recovery_model_desc, d.log_reuse_wait_desc
ORDER BY VLFCount DESC;

-- To fix a high count: back up the log (FULL recovery), shrink the log file,
-- then grow it back in one or a few large steps, for example:
-- USE [MyDB];
-- DBCC SHRINKFILE (N'MyDB_log', 1);
-- ALTER DATABASE [MyDB] MODIFY FILE (NAME = N'MyDB_log', SIZE = 8192MB, FILEGROWTH = 1024MB);