|
| 1 | +--- |
| 2 | +title: "sys.dm_os_linux_disk_stats (Transact-SQL)" |
| 3 | +description: sys.dm_os_linux_disk_stats returns a table with detailed Linux CPU statistics, offering system-level insights beyond SQL Server. |
| 4 | +author: rwestMSFT |
| 5 | +ms.author: randolphwest |
| 6 | +ms.date: 01/13/2026 |
| 7 | +ms.service: sql |
| 8 | +ms.subservice: system-objects |
| 9 | +ms.topic: "reference" |
| 10 | +f1_keywords: |
| 11 | + - "dm_os_linux_disk_stats" |
| 12 | + - "sys.dm_os_linux_disk_stats_TSQL" |
| 13 | + - "dm_os_linux_disk_stats_TSQL" |
| 14 | + - "sys.dm_os_linux_disk_stats" |
| 15 | +helpviewer_keywords: |
| 16 | + - "sys.dm_os_linux_disk_stats dynamic management view" |
| 17 | +dev_langs: |
| 18 | + - "TSQL" |
| 19 | +--- |
| 20 | +# sys.dm_os_linux_disk_stats (Transact-SQL) |
| 21 | + |
| 22 | +[!INCLUDE [sqlserver2025-linux](../../includes/applies-to-version/sqlserver2025-linux.md)] |
| 23 | + |
| 24 | +Returns a table with disk I/O statistics for each Linux device, showing total activity beyond SQL Server, in [!INCLUDE [sssql25-md](../../includes/sssql25-md.md)] Cumulative Update (CU) 1 and later versions. |
| 25 | + |
| 26 | +The DMV returns one row per Linux disk device. |
| 27 | + |
| 28 | +| Column name | Data type | Nullable | Description | |
| 29 | +| --- | --- | --- | --- | |
| 30 | +| `dev_name` | **nvarchar(256)** | No | Device name. | |
| 31 | +| `major_num` | **bigint** | No | Major device number. | |
| 32 | +| `minor_num` | **bigint** | No | Minor device number. | |
| 33 | +| `reads_completed` | **bigint** | No | Number of reads completed. | |
| 34 | +| `reads_merged` | **bigint** | No | Number of adjacent reads merged into a single request. | |
| 35 | +| `sectors_read` | **bigint** | No | Number of sectors read. | |
| 36 | +| `read_time_ms` | **bigint** | No | Milliseconds spent servicing reads. | |
| 37 | +| `writes_completed` | **bigint** | No | Number of writes completed. | |
| 38 | +| `writes_merged` | **bigint** | No | Number of adjacent writes merged into a single request. | |
| 39 | +| `sectors_written` | **bigint** | No | Number of sectors written. | |
| 40 | +| `write_time_ms` | **bigint** | No | Milliseconds spent servicing writes. | |
| 41 | +| `ios_in_progress` | **bigint** | No | Number of IOs currently in request queues. | |
| 42 | +| `io_time_ms` | **bigint** | No | Milliseconds the device spent doing I/O. | |
| 43 | +| `weighted_io_time_ms` | **bigint** | No | Weighted number of milliseconds spent doing I/Os. | |
| 44 | + |
| 45 | +## Permissions |
| 46 | + |
| 47 | +Requires `VIEW SERVER PERFORMANCE STATE` permission on the server. |
| 48 | + |
| 49 | +## Remarks |
| 50 | + |
| 51 | +- **Host level scope**: |
| 52 | + The results reflect all activity on the device, including SQL Server, other services, and background system operations. To attribute database workload effects, correlate these results with SQL Server wait statistics, such as `WRITELOG` and `PAGEIOLATCH_*`. |
| 53 | + |
| 54 | +- **Interpret time columns**: |
| 55 | + |
| 56 | + | Measure | Calculation | |
| 57 | + | --- | --- | |
| 58 | + | Average read latency (ms/op) | `read_time_ms / NULLIF(reads_completed, 0)` | |
| 59 | + | Average write latency (ms/op) | `write_time_ms / NULLIF(writes_completed, 0)` | |
| 60 | + | Device utilization (%) over an interval | `io_time_ms / (elapsed_ms) * 100` | |
| 61 | + | Average queue length | `weighted_io_time_ms / elapsed_ms` | |
| 62 | + |
| 63 | +- **Sector units**: Linux commonly reports sectors in 512-byte units. Validate your environment's sector size and adjust calculations accordingly. |
| 64 | + |
| 65 | +- **Use with care in multitenant hosts**: High values can originate from non-SQL Server workloads. Correlate with system tools or other DMVs for attribution. |
| 66 | + |
| 67 | +Use this DMV with other Linux-specific DMVs, such as [sys.dm_os_linux_disk_stats](sys-dm-os-linux-disk-stats-transact-sql.md) and [sys.dm_os_linux_net_stats](sys-dm-os-linux-net-stats-transact-sql.md), for holistic monitoring. |
| 68 | + |
| 69 | +### Usage scenarios |
| 70 | + |
| 71 | +- **Log flush slowness (availability groups or standalone)**: High `write_time_ms` / `writes_completed` with elevated `io_time_ms` indicates device-level write latency. Corroborate with `WRITELOG` waits. |
| 72 | + |
| 73 | +- **Checkpoint or read heavy workloads**: Rising `read_time_ms` / `reads_completed` with sustained `read_MBps` suggests throughput constrained by latency. Consider storage tier or queue settings. |
| 74 | + |
| 75 | +- **Noisy neighbors on shared hosts**: Spikes in `device_utilization_pct` and `avg_queue_length` without corresponding SQL Server workload changes imply external I/O pressure. Validate with host monitoring. |
| 76 | + |
| 77 | +## Examples |
| 78 | + |
| 79 | +### A. Current device activity snapshot |
| 80 | + |
| 81 | +This query returns an activity snapshot for the current storage device. |
| 82 | + |
| 83 | +```sql |
| 84 | +SELECT dev_name, |
| 85 | + reads_completed, |
| 86 | + read_time_ms, |
| 87 | + writes_completed, |
| 88 | + write_time_ms, |
| 89 | + ios_in_progress, |
| 90 | + io_time_ms, |
| 91 | + weighted_io_time_ms |
| 92 | +FROM sys.dm_os_linux_disk_stats |
| 93 | +ORDER BY io_time_ms DESC; |
| 94 | +``` |
| 95 | + |
| 96 | +### B. Latency and throughput over a 10-second sample window |
| 97 | + |
| 98 | +The script samples the DMV twice and computes deltas for latency (milliseconds per operation), throughput (MB per second), utilization (percentage), and queue length. Adjust `@SectorBytes` to match your device configuration. |
| 99 | + |
| 100 | +```sql |
| 101 | +DECLARE @SectorBytes AS INT = 512; |
| 102 | + |
| 103 | +-- verify sector size for your environment |
| 104 | +DECLARE @SampleMs AS INT = 10000; |
| 105 | + |
| 106 | +IF OBJECT_ID('tempdb..#before') IS NOT NULL |
| 107 | + DROP TABLE #before; |
| 108 | + |
| 109 | +IF OBJECT_ID('tempdb..#after') IS NOT NULL |
| 110 | + DROP TABLE #after; |
| 111 | + |
| 112 | +SELECT dev_name, |
| 113 | + reads_completed, |
| 114 | + reads_merged, |
| 115 | + sectors_read, |
| 116 | + read_time_ms, |
| 117 | + writes_completed, |
| 118 | + writes_merged, |
| 119 | + sectors_written, |
| 120 | + write_time_ms, |
| 121 | + ios_in_progress, |
| 122 | + io_time_ms, |
| 123 | + weighted_io_time_ms |
| 124 | +INTO #before |
| 125 | +FROM sys.dm_os_linux_disk_stats; |
| 126 | + |
| 127 | +WAITFOR DELAY '00:00:10'; |
| 128 | + |
| 129 | +SELECT dev_name, |
| 130 | + reads_completed, |
| 131 | + reads_merged, |
| 132 | + sectors_read, |
| 133 | + read_time_ms, |
| 134 | + writes_completed, |
| 135 | + writes_merged, |
| 136 | + sectors_written, |
| 137 | + write_time_ms, |
| 138 | + ios_in_progress, |
| 139 | + io_time_ms, |
| 140 | + weighted_io_time_ms |
| 141 | +INTO #after |
| 142 | +FROM sys.dm_os_linux_disk_stats; |
| 143 | + |
| 144 | +WITH deltas |
| 145 | +AS (SELECT a.dev_name, |
| 146 | + a.reads_completed - b.reads_completed AS d_reads, |
| 147 | + a.read_time_ms - b.read_time_ms AS d_read_ms, |
| 148 | + a.sectors_read - b.sectors_read AS d_read_sectors, |
| 149 | + a.writes_completed - b.writes_completed AS d_writes, |
| 150 | + a.write_time_ms - b.write_time_ms AS d_write_ms, |
| 151 | + a.sectors_written - b.sectors_written AS d_write_sectors, |
| 152 | + a.io_time_ms - b.io_time_ms AS d_io_ms, |
| 153 | + a.weighted_io_time_ms - b.weighted_io_time_ms AS d_weighted_io_ms |
| 154 | + FROM #after AS a |
| 155 | + INNER JOIN #before AS b |
| 156 | + ON a.dev_name = b.dev_name) |
| 157 | +SELECT dev_name, |
| 158 | + -- latency (ms/op) |
| 159 | + CAST (d_read_ms / NULLIF (d_reads, 0) AS DECIMAL (18, 2)) AS avg_read_latency_ms, |
| 160 | + CAST (d_write_ms / NULLIF (d_writes, 0) AS DECIMAL (18, 2)) AS avg_write_latency_ms, |
| 161 | + -- throughput (MB/s) |
| 162 | + CAST ((d_read_sectors * @SectorBytes) / (@SampleMs / 1000.0) / 1048576.0 AS DECIMAL (18, 2)) AS read_MBps, |
| 163 | + CAST ((d_write_sectors * @SectorBytes) / (@SampleMs / 1000.0) / 1048576.0 AS DECIMAL (18, 2)) AS write_MBps, |
| 164 | + -- utilization (%) |
| 165 | + CAST (d_io_ms / @SampleMs * 100.0 AS DECIMAL (5, 2)) AS device_utilization_pct, |
| 166 | + -- average queue length |
| 167 | + CAST (d_weighted_io_ms / @SampleMs AS DECIMAL (18, 2)) AS avg_queue_length |
| 168 | +FROM deltas |
| 169 | +ORDER BY device_utilization_pct DESC; |
| 170 | +``` |
| 171 | + |
| 172 | +### C. Identify devices with high merge ratios |
| 173 | + |
| 174 | +This example identifies devices with high merge ratios, indicating possible I/O coalescing. |
| 175 | + |
| 176 | +```sql |
| 177 | +SELECT dev_name, |
| 178 | + reads_completed, |
| 179 | + reads_merged, |
| 180 | + writes_completed, |
| 181 | + writes_merged, |
| 182 | + CAST (reads_merged / NULLIF (reads_completed, 0) AS DECIMAL (10, 2)) AS read_merge_ratio, |
| 183 | + CAST (writes_merged / NULLIF (writes_completed, 0) AS DECIMAL (10, 2)) AS write_merge_ratio |
| 184 | +FROM sys.dm_os_linux_disk_stats |
| 185 | +ORDER BY write_merge_ratio DESC, read_merge_ratio DESC; |
| 186 | +``` |
| 187 | + |
| 188 | +### D. Watch queue depth live |
| 189 | + |
| 190 | +This example shows the live queue depth, which is useful for incident triage. |
| 191 | + |
| 192 | +```sql |
| 193 | +SELECT TOP (20) dev_name, |
| 194 | + ios_in_progress, |
| 195 | + io_time_ms, |
| 196 | + weighted_io_time_ms |
| 197 | +FROM sys.dm_os_linux_disk_stats |
| 198 | +ORDER BY ios_in_progress DESC, |
| 199 | + weighted_io_time_ms DESC; |
| 200 | +``` |
| 201 | + |
| 202 | +## Related content |
| 203 | + |
| 204 | +- [sys.dm_os_linux_cpu_stats (Transact-SQL)](sys-dm-os-linux-cpu-stats-transact-sql.md) |
| 205 | +- [sys.dm_os_linux_net_stats (Transact-SQL)](sys-dm-os-linux-net-stats-transact-sql.md) |
| 206 | +- [Performance best practices and configuration guidelines for SQL Server on Linux](../../linux/sql-server-linux-performance-best-practices.md) |
0 commit comments