In this lesson, you will learn how SQL Server interacts with storage and why many “slow database” incidents are actually
I/O performance problems. You will learn how SQL Server reads and writes data, how to measure disk latency correctly,
how to identify whether storage is the real bottleneck, and what practical fixes work in production.
Big Idea: SQL Server is built on storage. Even a “perfect” query can be slow if it must read too many pages from disk,
if the storage is slow, or if the log can’t flush fast enough. A DBA must learn to separate:
query inefficiency (too many reads) from storage inefficiency (reads are slow).
120–180 minutes (concepts + measurement + labs)
SQL Server stores data in 8 KB pages. When a query needs data, SQL Server tries to read pages from memory first.
If the page is not in memory, SQL Server must read it from disk (physical I/O). This is why the buffer pool matters.
Key teaching point: Many performance problems are not “disk is slow.” They are “query reads too much.”
If you reduce logical reads, you reduce physical I/O pressure.
SQL Server storage is not one thing. Data files and log files behave differently and need different performance profiles.
Key teaching point: If transactions are slow and wait on log flush, your query tuning might not help.
You must check log I/O and write patterns.
DBAs must speak the language of storage performance. The most important metrics are:
Key teaching point: High throughput can still feel “slow” if latency is high.
OLTP systems usually suffer first from latency, not bandwidth.
Wait stats are one of the fastest ways to detect storage pressure. Here are common I/O signals:
Key teaching point: Waits show where time went; you must still identify which queries are generating the I/O.
SQL Server exposes file-level I/O stats through DMVs. This helps you answer:
“Which database file is slow?” and “Is the log file the bottleneck?”
/* File latency (ms) by database file */
SELECT
DB_NAME(vfs.database_id) AS database_name,
mf.type_desc AS file_type,
mf.name AS logical_name,
mf.physical_name,
vfs.num_of_reads,
vfs.num_of_writes,
vfs.io_stall_read_ms,
vfs.io_stall_write_ms,
CAST(vfs.io_stall_read_ms / NULLIF(vfs.num_of_reads,0) AS decimal(18,2)) AS avg_read_latency_ms,
CAST(vfs.io_stall_write_ms / NULLIF(vfs.num_of_writes,0) AS decimal(18,2)) AS avg_write_latency_ms,
CAST((vfs.io_stall_read_ms + vfs.io_stall_write_ms) /
NULLIF((vfs.num_of_reads + vfs.num_of_writes),0) AS decimal(18,2)) AS avg_total_latency_ms
FROM sys.dm_io_virtual_file_stats(NULL, NULL) vfs
JOIN sys.master_files mf
ON vfs.database_id = mf.database_id
AND vfs.file_id = mf.file_id
ORDER BY avg_total_latency_ms DESC;
How to interpret: High avg_read_latency_ms suggests slow data reads (PAGEIOLATCH).
High avg_write_latency_ms on log files suggests log flush pressure (WRITELOG).
Always compare to your baseline and workload type.
/* Top cached queries by total logical reads */ SELECT TOP (25) qs.total_logical_reads AS total_logical_reads, (qs.total_logical_reads / NULLIF(qs.execution_count,0)) AS avg_logical_reads, qs.execution_count, (qs.total_elapsed_time / NULLIF(qs.execution_count,0)) AS avg_elapsed_time, DB_NAME(st.dbid) AS database_name, LEFT(st.text, 4000) AS query_text FROM sys.dm_exec_query_stats qs CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st ORDER BY qs.total_logical_reads DESC;
How to interpret: High logical reads usually means scans, missing indexes, poor filtering, or inefficient joins.
Reducing logical reads is often the best I/O optimization.
TempDB is used for sorting, hashing, version store, spills, and many internal operations. When TempDB is slow or contended,
the entire SQL Server instance can slow down.
Key teaching point: Some I/O problems are actually “query plan problems” that spill to TempDB.
Fixing the query can remove the storage pressure.
Key teaching point: If you only “upgrade disks” without reducing logical reads, you will buy time but not solve root causes.
Students will collect evidence of file latency, identify the worst data/log file, and identify top queries by logical reads.
Prompt:
“What would you investigate first if users complain that ‘saving orders is slow’ but reporting queries are fine?
Which file type (data vs log) would you suspect and why?”
In the next lesson, we will cover Locking, Blocking, and Concurrency in SQL Server.
You will learn why “slow” often means “waiting,” how SQL Server locks work, how to diagnose blocking chains,
how deadlocks happen, and how to tune concurrency safely without breaking correctness.
Not a member yet? Register now
Are you a member? Login now