IO_STALL pregunta y comprensión


9

Estoy recopilando IO_STALLS de sys.dm_io_virtual_file_stats cada 5 minutos y luego hago un delta para ver qué archivos están siendo los más afectados por IO.

En un período de 5 minutos obtengo un delta de 5826331 ms, que es 97 minutos.

Estoy un poco confundido por esto, ¿esto dice que una operación comenzó hace 97 minutos y acaba de terminar en ese punto y, por lo tanto, registró ese tiempo de espera?

Gracias

Código agregado según lo solicitado:

/*

USE [SysDBA]
GO
*/
/****** Object:  Table [dbo].[DISKIOPS]    Script Date: 04/07/2013 11:40:15 ******/
/*
DROP TABLE [dbo].[DISKIOPS]
GO
*/
--Create the table
/****** Object:  Table [dbo].[DISKIOPS]    Script Date: 04/07/2013 11:40:15 ******/
/*
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[DISKIOPS](
    [IO_STALL] [bigint] NULL,
    [IO_STALL_READ_MS] [bigint] NULL,
    [IO_STALL_WRITE_MS] [bigint] NULL,
    [NUM_OF_READS] [bigint] NULL,
    [NUM_OF_WRITES] [bigint] NULL,
    [SIZE_ON_DISK_MB] [bigint] NULL,
    [DBNAME] [varchar](max) NULL,
    [NAME] [varchar](max) NULL,
    [FILE_ID] [int] NULL,
    [DB_FILE_TYPE] [varchar](max) NULL,
    [DISK] [varchar](max) NULL,
    [FILE_LOCATION] [varchar](max) NULL,
    [TIMESTAMP] [datetime] NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

*/

--Capture IO information from DMV and query to find deltas over time.
/*
USE [SysDBA]
GO

INSERT INTO [dbo].[DISKIOPS]
           ([IO_STALL]
           ,[IO_STALL_READ_MS]
           ,[IO_STALL_WRITE_MS]
           ,[NUM_OF_READS]
           ,[NUM_OF_WRITES]
           ,[SIZE_ON_DISK_MB]
           ,[DBNAME]
           ,[NAME]
           ,[FILE_ID]
           ,[DB_FILE_TYPE]
           ,[DISK]
           ,[FILE_LOCATION]
           ,[TIMESTAMP])
SELECT a.io_stall, a.io_stall_read_ms, a.io_stall_write_ms, a.num_of_reads, 
a.num_of_writes, 
--a.sample_ms, a.num_of_bytes_read, a.num_of_bytes_written,
( ( a.size_on_disk_bytes / 1024 ) / 1024.0 ) AS size_on_disk_mb, 
db_name(a.database_id) AS dbname, 
b.name, a.file_id, 
db_file_type = CASE 
                   WHEN a.file_id = 2 THEN 'Log' 
                   ELSE 'Data' 
                   END, 
UPPER(SUBSTRING(b.physical_name, 1, 2)) AS disk_location,
b.physical_name AS File_location,
GETDATE() AS Timestamp
FROM sys.dm_io_virtual_file_stats (NULL, NULL) a 
JOIN sys.master_files b ON a.file_id = b.file_id 
AND a.database_id = b.database_id
GO
*/
DECLARE @File_Name VARCHAR(8000),
        @Disk VARCHAR(5)
SET @File_Name = 'DBTEST'
SET @Disk = 'I:'
--Code to pull out deltas between collected IO stats.
;WITH IOPS   ([IO_STALL]
           ,[IO_STALL_READ_MS]
           ,[IO_STALL_WRITE_MS]
           ,[NUM_OF_READS]
           ,[NUM_OF_WRITES]
           ,[SIZE_ON_DISK_MB]
           ,[DBNAME]
           ,[NAME]
           ,[FILE_ID]
           ,[DB_FILE_TYPE]
           ,[DISK]
           ,[FILE_LOCATION]
           ,[TIMESTAMP]
           ,[ROW])
AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY FILE_LOCATION ORDER BY TIMESTAMP DESC) AS [ROW]
FROM dbo.DISKIOPS 
)

SELECT MAX([IO2].[IO_STALL] - [IO1].[IO_STALL])
FROM IOPS IO1 JOIN IOPS IO2 ON IO1.ROW = (IO2.ROW+1)
WHERE IO1.NAME = IO2.NAME
AND IO1.Disk = @Disk

1
io_stallpor sí solo no significa demasiado. Si en 10 segundos tuviste 1000 operaciones detenidas durante 1 segundo cada una, tendrás 1000 segundos de paradas. Eso sería más de 16 minutos de paradas en 10 segundos. Debe correlacionar esto con las operaciones de E / S. ¿Puede publicar su consulta real en su pregunta?
Thomas Stringer

Hola, he agregado el código, estaba teniendo algunos problemas para formatearlo, así que espero que esté bien.
Tom

Respuestas:


10

Comentario de pregunta pegado a continuación:

io_stallpor sí solo no significa demasiado. Si en 10 segundos tuviste 1000 operaciones detenidas durante 1 segundo cada una, tendrás 1000 segundos de paradas. Eso sería más de 16 minutos de paradas en 10 segundos. Necesita correlacionar esto con las operaciones de E / S ...

Lo anterior es un buen ejemplo de cómo puedes ver números monumentales y aparentemente exagerados. Por sí mismo, io_stallrealmente no significa nada. Debe conocer la escala de las operaciones de E / S para ese bloqueo acumulativo.

En lugar de tener esto:

SELECT MAX([IO2].[IO_STALL] - [IO1].[IO_STALL])
FROM IOPS IO1 JOIN IOPS IO2 ON IO1.ROW = (IO2.ROW+1)
...

Debe dividir el bloqueo por operaciones de E / S para obtener el bloqueo promedio por E / S (o por lectura, escritura o cualquier granularidad que esté buscando). En otras palabras, mi recomendación sería modificar su consulta para que se vea así:

SELECT
    MAX(([IO2].[IO_STALL] - [IO1].[IO_STALL]) / (IO2.NUM_OF_READS + IO2.NUM_OF_WRITES - IO1.NUM_OF_READS - IO1.NUM_OF_WRITES))
FROM IOPS IO1 JOIN IOPS IO2 ON IO1.ROW = (IO2.ROW+1)

Y luego debe tener una cláusula de predicado adicional para asegurarse de que no está dividiendo por cero:

...
WHERE IO1.NAME = IO2.NAME
and (IO2.NUM_OF_READS + IO2.NUM_OF_WRITES - IO1.NUM_OF_READS - IO1.NUM_OF_WRITES) > 0
AND IO1.Disk = @Disk

Lo que esto hace básicamente es calcular el promedio io_stallpor operación de E / S . Por sí mismo, un valor alto io_stallpodría significar simplemente una mayor carga de trabajo y no necesariamente el signo de un problema.


2
Ah, claro, lo entiendo, muchas gracias, espero que mi error resulte útil para otros.
Tom

2
Es un error común, no solo con las estadísticas de archivos virtuales, sino también con las estadísticas de espera. Me alegro de que haya ayudado!
Thomas Stringer
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.