IO_STALL soru ve anlayışı


9

Her 5 dakikada bir sys.dm_io_virtual_file_stats IO_STALLS topluyorum ve daha sonra hangi dosyaların IO tarafından en çok etkilendiğini görmek için bir delta yapıyorum.

Bir 5 dakikalık sürede, 97 dakika olan 5826331 ms'lik bir delta alıyorum.

Biraz kafam karıştı, bu 97 dakika önce başlayan bir operasyonun sadece o noktada bittiğini ve bu bekleme süresini kaydettiğini mi söylüyor?

Teşekkürler

İstendiği gibi kod eklendi:

/*

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_stalltek başına çok fazla bir şey ifade etmiyor. 10 saniyede 1 saniye boyunca 1000 işleminiz olduysa, 1000 saniyelik duraklarınız olacaktır. Bu 10 saniyede 16 dakikadan fazla durak anlamına gelir. Bunu G / Ç işlemleri ile ilişkilendirmeniz gerekir. Asıl sorgunuzu sorunuza gönderebilir misiniz?
Thomas Stringer

Merhaba orada kod ekledim, ben biçimlendirmek için almakta biraz sorun vardı, bu yüzden onun ok umuyoruz.
Tom

Yanıtlar:


10

Soru yorumu aşağıda yapıştırıldı:

io_stalltek başına çok fazla bir şey ifade etmiyor. 10 saniyede 1 saniye boyunca 1000 işleminiz olduysa, 1000 saniyelik duraklarınız olacaktır. Bu 10 saniyede 16 dakikadan fazla durak anlamına gelir. Bunu ES operasyonları ile ilişkilendirmeniz gerekiyor ...

Yukarıdaki, anıtsal ve görünüşte abartılı sayıları nasıl görebileceğinize oldukça iyi bir örnektir. Tek başına, io_stallhiçbir şey ifade etmiyor. Bu birikimli durak için G / Ç işlemlerinin ölçeğini bilmeniz gerekir.

Bunun yerine:

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

G / Ç başına ortalama duraklamayı (veya okuma veya yazma başına veya aradığınız ayrıntı düzeyi) elde etmek için durakları G / Ç işlemlerine bölmeniz gerekir. Başka bir deyişle, önerim sorgunuzu aşağıdaki gibi görünecek şekilde değiştirmek olacaktır:

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)

Ve sonra sıfıra bölmediğinizden emin olmak için fazladan bir önermeye sahip olmanız gerekir:

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

Bunun temel olarak yaptığı G / Ç işlemi başına ortalamayıio_stall hesaplamaktır . Tek başına bir yüksek io_stall, sadece bir sorunun işareti olmak zorunda değil, daha yüksek bir iş yükü anlamına gelebilir.


2
Ah, anlıyorum, çok teşekkürler, umarım benim hatam başkalarına faydalı olacaktır.
Tom

2
Bu, yalnızca sanal dosya istatistikleriyle değil, aynı zamanda bekleme istatistikleriyle de yaygın bir hatadır. Yardımcı oldu sevindim!
Thomas Stringer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.