IO_STALL domanda e comprensione


9

Raccolgo IO_STALLS da sys.dm_io_virtual_file_stats ogni 5 minuti e quindi eseguo un delta per vedere quali file sono maggiormente interessati da IO.

In un periodo di 5 minuti ottengo un delta di 5826331 ms che è 97 minuti.

Sono un po 'confuso da questo, sta dicendo che un'operazione iniziata 97 minuti fa è appena terminata a quel punto e quindi registrato quel tempo di attesa?

Grazie

Codice aggiunto come richiesto:

/*

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_stallda solo non significa troppo. Se in 10 secondi hai avuto 1000 operazioni in stallo per 1 secondo ciascuna, avrai 1000 secondi di bancarelle. Sarebbero 16+ minuti di bancarelle in 10 secondi. È necessario correlarlo con le operazioni di I / O. Puoi pubblicare la tua domanda effettiva nella tua domanda?
Thomas Stringer,

Ciao, ho aggiunto il codice, ho avuto un po 'di problemi a formattarlo, quindi spero sia ok.
Tom,

Risposte:


10

Commento alla domanda incollato di seguito:

io_stallda solo non significa troppo. Se in 10 secondi hai avuto 1000 operazioni in stallo per 1 secondo ciascuna, avrai 1000 secondi di bancarelle. Sarebbero 16+ minuti di bancarelle in 10 secondi. È necessario correlarlo con le operazioni di I / O ...

Quanto sopra è un ottimo esempio di come si possano vedere numeri monumentali e apparentemente esagerati. Di per sé, io_stallnon significa davvero nulla. È necessario conoscere la scala delle operazioni di I / O per lo stallo cumulativo.

Invece di avere questo:

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

È necessario dividere lo stallo per operazioni I / O per ottenere lo stallo medio per I / O (o per lettura, scrittura o qualsiasi granularità che si sta cercando). In altre parole, la mia raccomandazione sarebbe quella di modificare la tua query in modo che assomigli a questo:

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 quindi devi avere una clausola di predicato aggiuntiva per assicurarti di non dividere per 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

Quello che fa è fondamentalmente calcolare la media io_stallper ogni operazione di I / O . Di per sé, un alto io_stallpotrebbe significare semplicemente un carico di lavoro più elevato e non necessariamente il segno di un problema.


2
Ah giusto capisco, grazie mille, spero che il mio errore si rivelerà utile agli altri.
Tom,

2
È un errore comune, non solo con le statistiche dei file virtuali, ma anche le statistiche di attesa. Sono contento che abbia aiutato!
Thomas Stringer,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.