Overview
This query should show you all database files on your SQL Server instance that exceed the recommended thesholds.
According to SQL Server Central [http://www.sqlservercentral.com/articles/ssc+clinic/74097/]
- Less than 10 milliseconds (ms) = very good
- Between 10-20 ms = okay
- Between 20-50 ms = slow
- Greater than 50-100 ms = potentially serious IO bottleneck
- Greater than 100 ms = definite IO bottleneck
T-SQL Script
/*
For SQL Versions older than 2012.. replace
sys.dm_io_virtual_file_stats(NULL, NULL)
with
sys.dm_io_virtual_file_stats(-1, -1)
*/
IF OBJECT_ID('tempdb..##dbFiles') IS NOT NULL
DROP TABLE ##dbFiles
GO
/*
table to hold all database files
*/
CREATE TABLE ##dbFiles (
DBName SYSNAME ,
name VARCHAR(200) ,
physical_name VARCHAR(2000) ,
type_desc VARCHAR(200) ,
state_desc VARCHAR(200) ,
FILE_ID INT )
GO
/*
get all the database files for the sql instance
into a table
*/
EXEC sp_msforeachdb 'use [?]
insert into ##dbFiles
select ''?'' as [DBName],name , physical_name,type_desc, state_desc,file_id
from sys.database_files'
/*
FIND FILES THAT HAVE UNACCEPTABLE DISK LATENCY
AND JOIN TO DATABASE_FILES TABLE TO GIVE FRIENDLY NAMES
THE VIRTUAL FILE STATS ARE FROM WHEN SQL SERVER WAS LAST RESTARTED
> 20ms data and > 15ms logs
*/
DECLARE @DataReadLatency_ms INT,@DataWriteLatency_ms INT
DECLARE @LogReadLatency_ms INT,@LogWriteLatency_ms INT
SET @DataReadLatency_ms = 20
SET @DataWriteLatency_ms = 20
SET @LogReadLatency_ms = 15
SET @LogWriteLatency_ms = 15
SELECT DB_NAME(database_id) AS 'db' ,
df.file_id ,
io_stall_read_ms / NULLIF(num_of_reads,0) AS 'AVG READ TRANSFER/SEC' ,
io_stall_write_ms / NULLIF(num_of_writes,0) AS 'AVG WRITE TRANSFER/SEC' ,
size_on_disk_bytes ,
df.name ,
df.physical_name ,
df.type_desc
FROM sys.dm_io_virtual_file_stats(NULL, NULL) stat
JOIN ##dbFiles df ON stat.file_id = df.FILE_ID
AND df.DBName = DB_NAME(stat.database_id)
WHERE num_of_reads > 0
AND num_of_writes > 0
-- ONLY INCLUDE UNACCEPTABLE LATENCY AND NOT DIV/0
AND ((
ISNULL((io_stall_read_ms / NULLIF(num_of_reads,0)),0) > @DataReadLatency_ms AND type_desc = 'ROWS'
OR
ISNULL((io_stall_write_ms / NULLIF(num_of_writes,0)),0) > @DataWriteLatency_ms AND type_desc = 'ROWS'
)
OR
(
ISNULL((io_stall_read_ms / NULLIF(num_of_reads,0)),0) > @LogReadLatency_ms AND type_desc = 'LOG'
OR
ISNULL((io_stall_write_ms / NULLIF(num_of_writes,0)),0) > @LogWriteLatency_ms AND type_desc = 'LOG'
))
-- clean up
DROP TABLE ##dbFiles








