IO_STALL pergunta e entendimento

9

Estou coletando IO_STALLS de sys.dm_io_virtual_file_stats a cada 5 minutos e depois faço um delta para ver quais arquivos estão sendo mais afetados pelo IO.

Em um período de 5 minutos, recebo um delta de 5826331 ms, que é 97 minutos.

Estou um pouco confuso com isso, isso está dizendo que uma operação iniciada há 97 minutos apenas terminou naquele ponto e, portanto, registrou esse tempo de espera?

obrigado

Código adicionado conforme 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
Tom
fonte
11
io_stallpor si só não significa muito. Se em 10 segundos você tiver 1000 operações paralisadas por 1 segundo cada, terá 1000 segundos de paralisações. Seriam mais de 16 minutos de barracas em 10 segundos. Você precisa correlacionar isso com operações de E / S. Você pode postar sua consulta real na sua pergunta?
9786 Thomas Stringer #
Olá, eu adicionei o código, estava tendo um pouco de dificuldade para obtê-lo para o formato, então espero que esteja tudo bem.
Tom

Respostas:

10

Comentário da pergunta colado abaixo:

io_stallpor si só não significa muito. Se em 10 segundos você tiver 1000 operações paralisadas por 1 segundo cada, terá 1000 segundos de paralisações. Seriam mais de 16 minutos de barracas em 10 segundos. Você precisa correlacionar isso com operações de E / S ...

O exemplo acima é um bom exemplo de como você pode ver números monumentais e aparentemente exagerados. Por si só, io_stallrealmente não significa nada. Você precisa conhecer a escala das operações de E / S para essa paralisação cumulativa.

Em vez de ter isso:

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

Você precisa dividir a paralisação por operações de E / S para obter a paralisação média por E / S (ou por leitura, gravação ou qualquer granularidade que esteja procurando). Em outras palavras, minha recomendação seria modificar sua consulta para algo parecido com isto:

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)

E então você precisa ter uma cláusula de predicado extra para garantir que você não esteja dividindo por zero:

...
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

O que isso basicamente faz é calcular a média io_stallpor operação I / O . Por si só, uma alta io_stallpoderia significar simplesmente uma carga de trabalho mais alta e não necessariamente o sinal de um problema.

Thomas Stringer
fonte
2
Ah, entendo, muito obrigado, espero que meu erro seja útil para os outros.
Tom
2
É um erro comum, não apenas nas estatísticas de arquivos virtuais, mas também nas estatísticas de espera. Fico feliz que ajudou!
9788 Thomas Stringer #