En nuestro motor de base de datos contamos con varias database, cada una de ellas o alguno de sus files pueden estar alojadas en 1 o mas discos.
Ahora bien, el consumo de I/O es uno de los problemas mas frecuentes en performance, es un recurso mecánico y mucho mas lento que cualquier otro componente de nuestro equipo (Memoria y CPU).
Los problemas de I/O por lo general se dan por falta de índices o querys mas escritas, si siempre me traiga todos los registros para mostrar unos pocos estaré haciendo un consumo de I/O mucho mas grande de lo que debería.
Para poder medir como se esta comportando mi I/O podemos utilizar los contadores de Windows (por ejemplo el IDLE del disco físico que queremos medir).
Ahora bien, como podemos detectar cual base de datos y/o file de nuestro SQL son los que mas I/O consumen? para ello podemos utilizar una función llamada fn_virtualfilestats la cual se encuentra disponible en la versión 2000 , 2005 y 2008 de SQL Server.
Esta función básicamente nos retornada el listado de files y el consumo de I/O de cada una.
Aquí abajo les dejo un simple query el cual evalúa los I/O y el porcentaje sobre el total para poder detectar cuales files son los que mas consumen mi I/O
DECLARE @TOTAL_IO INT
DECLARE @TOTAL_BYTES INT
DECLARE @TOTAL_STALL INT
SELECT
@TOTAL_IO = SUM(NUMBERREADS + NUMBERWRITES),
@TOTAL_BYTES = SUM(BYTESREAD + BYTESWRITTEN),
@TOTAL_STALL = SUM(IOSTALLMS)
FROM ::FN_VIRTUALFILESTATS(NULL, NULL)
SELECT
[DBNAME] = DB_NAME(FN.[DBID]),
[FILENAME],
[NUMBERREADS],
[NUMBERWRITES],
[BYTESREAD],
[BYTESWRITTEN],
[IOSTALLMS],
[TOTALIO] = CAST((NUMBERREADS + NUMBERWRITES) AS BIGINT),
[TOTALBYTES] = (BYTESREAD + BYTESWRITTEN),
[AVGSTALLPERIO] = (1.0 * [IOSTALLMS] / ([NUMBERREADS] + [NUMBERWRITES] + 1)),
[AVGBYTESPERIO] = (1.0 * (BYTESREAD + BYTESWRITTEN) / (NUMBERREADS + NUMBERWRITES + 1)),
[%IO] = (100.0 * (NUMBERREADS + NUMBERWRITES) / @TOTAL_IO),
[%BYTES] = (100.0 * (BYTESREAD + BYTESWRITTEN) / @TOTAL_BYTES),
[%STALL] = (100.0 * IOSTALLMS / @TOTAL_STALL)
FROM ::FN_VIRTUALFILESTATS(NULL, NULL) AS Fn INNER JOIN SYSALTFILES F
ON Fn.FileId = F.fileid AND Fn.DbId = F.dbid
ORDER BY [%IO] DESC