About Me

Barking, Essex, United Kingdom
MCITP DBA ,MCITP BI & Oracle OCP 11G

Saturday, May 2, 2015

Storage Slow -Performance issue

 To isolate the disk Latency on FIle level .Use the below method. 

Create Procedure IOPending_Disk
(
@loopexecution int
)
AS begin

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[IOpending_Disktable]') AND type in (N'U'))
BEGIN
create table IOpending_Disktable
(
[Database]      nvarchar (256) ,
physical_name  nvarchar (520),
io_pending  int,
io_pending_ms_ticks bigint,
io_type nvarchar(120),
num_of_reads bigint,
num_of_writes bigint,
[date] datetime
)
END



DECLARE @MyDateTime DATETIME
SET @MyDateTime = DATEADD(s,1,GETDATE())
DECLARE @i INT = 1;
--Declare @loopexecution int
--set @loopexecution=2

WHILE (@i <= @loopexecution)
 BEGIN
  WAITFOR delay '00:00:05'

insert IOpending_Disktable ([Database],physical_name,io_pending,io_pending_ms_ticks,io_type,num_of_reads,num_of_writes,[date])

SELECT DB_NAME(mf.database_id) AS [Database], mf.physical_name,
r.io_pending, r.io_pending_ms_ticks, r.io_type, fs.num_of_reads, fs.num_of_writes,GETDATE() as [Date]
FROM sys.dm_io_pending_io_requests AS r
INNER JOIN sys.dm_io_virtual_file_stats(null,null) AS fs
ON r.io_handle = fs.file_handle
INNER JOIN sys.master_files AS mf
ON fs.database_id = mf.database_id
AND fs.file_id = mf.file_id
where r.io_pending_ms_ticks>50
ORDER BY r.io_pending, r.io_pending_ms_ticks DESC;

 SET  @i = @i + 1;

END

End



--To detect the wait type ,SQL Query and averageIOstalls over Disk Latency . Please use the below method.

USE [master]
GO
/****** Object:  StoredProcedure [dbo].[Faizal_Monitoring]    Script Date: 05/03/2015 18:58:43 ******/
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Faizal_Monitoring]') AND type in (N'P', N'PC'))
DROP PROCEDURE [dbo].[Faizal_Monitoring]
GO
/****** Object:  StoredProcedure [dbo].[Faizal_Monitoring]    Script Date: 05/03/2015 18:58:43 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Faizal_Monitoring]') AND type in (N'P', N'PC'))
BEGIN
EXEC dbo.sp_executesql @statement = N'CREATE Procedure [dbo].[Faizal_Monitoring]
As begin

/****** Object:  Table [dbo].[Wait_SnapshotStats]    Script Date: 05/03/2015 14:28:23 ******/
SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[Wait_SnapshotStats]'') AND type in (N''U''))
BEGIN
CREATE TABLE [dbo].[Wait_SnapshotStats](
      [wait_time_ms] [bigint] NULL,
      [signal_wait_time_ms] [bigint] NULL,
      [RealWait] [bigint] NULL,
      [wait_type] [nvarchar](60) NOT NULL,
      [updatedDate] datetime
) ON [PRIMARY]
END

/****** Object:  Table [dbo].[Query_SnapshotStats]    Script Date: 05/03/2015 14:28:23 ******/
SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[Query_SnapshotStats]'') AND type in (N''U''))
BEGIN
CREATE TABLE [dbo].[Query_SnapshotStats](
      [Duration] [bigint] NULL,
      [Time on CPU] [bigint] NULL,
      [Time blocked] [bigint] NULL,
      [Reads] [bigint] NULL,
      [Writes] [bigint] NULL,
      [CLR time] [bigint] NULL,
      [Executions] [bigint] NULL,
      [Individual Query] [nvarchar](max) NULL,
      [Parent Query] [nvarchar](max) NULL,
      [DatabaseName] [nvarchar](128) NULL,
      [updatedDate] datetime
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
END

/****** Object:  Table [dbo].[PerfmonCounters_SnapshotStats]    Script Date: 05/03/2015 14:28:23 ******/
SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[PerfmonCounters_SnapshotStats]'') AND type in (N''U''))
BEGIN
CREATE TABLE [dbo].[PerfmonCounters_SnapshotStats](
      [object_name] [nchar](128) NOT NULL,
      [counter_name] [nchar](128) NOT NULL,
      [instance_name] [nchar](128) NULL,
      [InitialValue] [bigint] NOT NULL,
      [FinalValue] [bigint] NOT NULL,
      [Change] [bigint] NULL,
      [% Change] [bigint] NULL,
      [updatedDate] datetime
) ON [PRIMARY]
END

/****** Object:  Table [dbo].[DiskIO_SnapshotStats]    Script Date: 05/03/2015 14:28:23 ******/
SET ANSI_NULLS ON

SET QUOTED_IDENTIFIER ON

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N''[dbo].[DiskIO_SnapshotStats]'') AND type in (N''U''))
BEGIN
CREATE TABLE [dbo].[DiskIO_SnapshotStats](
      [DBName] [nvarchar](128) NULL,
      [LogicalFileName] [sysname] NOT NULL,
      [physical_name] [nvarchar](260) NOT NULL,
      [Bytesread] [bigint] NULL,
      [BytesWritten] [bigint] NULL,
      [IOStallReadms] [bigint] NULL,
      [IOStallWriteMS] [bigint] NULL,
      [Numberofreads] [bigint] NULL,
      [Numberofwrites] [bigint] NULL,
      [AvgReadTransfersMS] [bigint] NULL,
      [AvgWriteTransfersMS] [bigint] NULL,
      [updatedDate] datetime
) ON [PRIMARY]
END



SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


SELECT
sql_handle, plan_handle, total_elapsed_time, total_worker_time
, total_logical_reads, total_logical_writes, total_clr_time
, execution_count, statement_start_offset, statement_end_offset
INTO #PreWorkQuerySnapShot
FROM sys.dm_exec_query_stats
SELECT
[object_name], [counter_name], [instance_name]
, [cntr_value], [cntr_type]
INTO #PreWorkOSSnapShot
FROM sys.dm_os_performance_counters
SELECT
wait_type, waiting_tasks_count
, wait_time_ms, max_wait_time_ms, signal_wait_time_ms
INTO #PreWorkWaitStats
FROM sys.dm_os_wait_stats

SELECT
 DB_NAME(filestats.database_id) AS DBName
 ,files.name AS LogicalFileName
 ,files.physical_name
 ,num_of_reads AS NumberReads
 ,num_of_writes AS NumberWrites
 ,num_of_bytes_read AS BytesRead
 ,num_of_bytes_written AS BytesWritten
 ,io_stall_read_ms AS IOStallReadMS
 ,io_stall_write_ms AS IOStallWriteMS
 into #prediskIOstats
FROM sys.dm_io_virtual_file_stats(-1,-1) filestats
INNER JOIN sys.master_files files
  ON filestats.file_id = files.file_id
  AND filestats.database_id = files.database_id
ORDER BY num_of_writes DESC


  WAITFOR delay ''00:01:30''

SELECT
wait_type, waiting_tasks_count, wait_time_ms
, max_wait_time_ms, signal_wait_time_ms
INTO #PostWorkWaitStats
FROM sys.dm_os_wait_stats

SELECT
[object_name], [counter_name], [instance_name]
, [cntr_value], [cntr_type]
INTO #PostWorkOSSnapShot
FROM sys.dm_os_performance_counters



SELECT
sql_handle, plan_handle, total_elapsed_time, total_worker_time
, total_logical_reads, total_logical_writes, total_clr_time
, execution_count, statement_start_offset, statement_end_offset
INTO #PostWorkQuerySnapShot
FROM sys.dm_exec_query_stats

SELECT
 DB_NAME(filestats.database_id) AS DBName
 ,files.name AS LogicalFileName
 ,files.physical_name
 ,num_of_reads AS NumberReads
 ,num_of_writes AS NumberWrites
 ,num_of_bytes_read AS BytesRead
 ,num_of_bytes_written AS BytesWritten
 ,io_stall_read_ms AS IOStallReadMS
 ,io_stall_write_ms AS IOStallWriteMS
 into #postdiskIOstats
FROM sys.dm_io_virtual_file_stats(-1,-1) filestats
INNER JOIN sys.master_files files
  ON filestats.file_id = files.file_id
  AND filestats.database_id = files.database_id
ORDER BY num_of_writes DESC


INSERT INTO [Query_SnapshotStats]
           ([Duration]
           ,[Time on CPU]
           ,[Time blocked]
           ,[Reads]
           ,[Writes]
           ,[CLR time]
           ,[Executions]
           ,[Individual Query]
           ,[Parent Query]
           ,[DatabaseName]
           ,[updatedDate])

SELECT
p2.total_elapsed_time - ISNULL(p1.total_elapsed_time, 0) AS [Duration]
, p2.total_worker_time - ISNULL(p1.total_worker_time, 0) AS [Time on CPU]
, (p2.total_elapsed_time - ISNULL(p1.total_elapsed_time, 0)) -
(p2.total_worker_time - ISNULL(p1.total_worker_time, 0))
AS [Time blocked]
, p2.total_logical_reads - ISNULL(p1.total_logical_reads, 0) AS [Reads]
, p2.total_logical_writes - ISNULL(p1.total_logical_writes, 0)
AS [Writes]
, p2.total_clr_time - ISNULL(p1.total_clr_time, 0) AS [CLR time]
, p2.execution_count - ISNULL(p1.execution_count, 0) AS [Executions]
, SUBSTRING (qt.text,p2.statement_start_offset/2 + 1,
((CASE WHEN p2.statement_end_offset = -1
THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2
ELSE p2.statement_end_offset
END - p2.statement_start_offset)/2) + 1) AS [Individual Query]
, qt.text AS [Parent Query]
, DB_NAME(qt.dbid) AS DatabaseName
,GETDATE() as lastupdated
FROM #PreWorkQuerySnapShot p1
RIGHT OUTER JOIN
#PostWorkQuerySnapShot p2 ON p2.sql_handle =
ISNULL(p1.sql_handle, p2.sql_handle)
AND p2.plan_handle = ISNULL(p1.plan_handle, p2.plan_handle)
AND p2.statement_start_offset =
ISNULL(p1.statement_start_offset, p2.statement_start_offset)
AND p2.statement_end_offset =
ISNULL(p1.statement_end_offset, p2.statement_end_offset)
CROSS APPLY sys.dm_exec_sql_text(p2.sql_handle) as qt
WHERE p2.execution_count != ISNULL(p1.execution_count, 0)
AND qt.text NOT LIKE ''--ThisRoutineIdentifier%''
ORDER BY [Duration] DESC

INSERT INTO [Wait_SnapshotStats]
           ([wait_time_ms]
           ,[signal_wait_time_ms]
           ,[RealWait]
           ,[wait_type]
           ,[updatedDate])

SELECT
p2.wait_time_ms - ISNULL(p1.wait_time_ms, 0) AS wait_time_ms
, p2.signal_wait_time_ms - ISNULL(p1.signal_wait_time_ms, 0) AS signal_wait_time_ms
, ((p2.wait_time_ms - ISNULL(p1.wait_time_ms, 0)) - (p2.signal_wait_time_ms - ISNULL(p1.signal_wait_time_ms, 0)))
AS RealWait
, p2.wait_type
,GETDATE() as lastupdated
FROM #PreWorkWaitStats p1
RIGHT OUTER JOIN
#PostWorkWaitStats p2 ON p2.wait_type = ISNULL(p1.wait_type, p2.wait_type)
WHERE p2.wait_time_ms - ISNULL(p1.wait_time_ms, 0) > 0
AND p2.wait_type NOT LIKE ''%SLEEP%''
AND p2.wait_type != ''WAITFOR''
ORDER BY RealWait DESC

INSERT INTO [dbo].[PerfmonCounters_SnapshotStats]
           ([object_name]
           ,[counter_name]
           ,[instance_name]
           ,[InitialValue]
           ,[FinalValue]
           ,[Change]
           ,[% Change]
           ,[updatedDate])
SELECT
p2.object_name, p2.counter_name, p2.instance_name
, ISNULL(p1.cntr_value, 0) AS InitialValue
, p2.cntr_value AS FinalValue
, p2.cntr_value - ISNULL(p1.cntr_value, 0) AS Change
, (p2.cntr_value - ISNULL(p1.cntr_value, 0)) * 100 / p1.cntr_value
AS [% Change]
,GETDATE() as lastupdated
FROM #PreWorkOSSnapShot p1
RIGHT OUTER JOIN
#PostWorkOSSnapShot p2 ON p2.object_name =
ISNULL(p1.object_name, p2.object_name)
AND p2.counter_name = ISNULL(p1.counter_name, p2.counter_name)
AND p2.instance_name = ISNULL(p1.instance_name, p2.instance_name)
WHERE p2.cntr_value - ISNULL(p1.cntr_value, 0) > 0
AND ISNULL(p1.cntr_value, 0) != 0
ORDER BY [% Change] DESC, Change DESC


select po.BytesRead-Pr.BytesRead as Bytesread,po.BytesWritten-pr.BytesWritten as BytesWritten,
po.IOStallReadMS-pr.IOStallReadMS as IOStallReadms,PO.IOStallWriteMS-Pr.IOStallWriteMS as IOStallWriteMS ,Po.NumberReads-pr.NumberReads as Numberofreads,
PO.NumberWrites-pr.NumberWrites as Numberofwrites,Po.DBName,PO.LogicalFileName,PO.physical_name
into #diskIOStates_Changes
 from #prediskIOstats as pr
inner join #postdiskIOstats as po
on pr.DBName=Po.DBName and Pr.LogicalFileName=Po.LogicalFileName

INSERT INTO [dbo].[DiskIO_SnapshotStats]
           ([DBName]
           ,[LogicalFileName]
           ,[physical_name]
           ,[Bytesread]
           ,[BytesWritten]
           ,[IOStallReadms]
           ,[IOStallWriteMS]
           ,[Numberofreads]
           ,[Numberofwrites]
           ,[AvgReadTransfersMS]
           ,[AvgWriteTransfersMS]
           ,[updatedDate])
   
select DBName,LogicalFileName,physical_name,Bytesread,BytesWritten,IOStallReadms,IOStallWriteMS,Numberofreads,Numberofwrites,
CASE WHEN (Numberofreads = 0) THEN 0 ELSE IOStallReadms / Numberofreads END AS AvgReadTransfersMS
,CASE WHEN (Numberofwrites = 0) THEN 0 ELSE IOStallWriteMS /Numberofwrites END AS AvgWriteTransfersMS
,GETDATE() as lastupdated
 from #diskIOStates_Changes

DROP TABLE #PreWorkQuerySnapShot
DROP TABLE #PostWorkQuerySnapShot
DROP TABLE #PostWorkWaitStats
DROP TABLE #PreWorkWaitStats
DROP TABLE #PreWorkOSSnapShot
DROP TABLE #PostWorkOSSnapShot
DROP TABLE #prediskIOstats
DROP TABLE #postdiskIOstats
Drop table #diskIOStates_Changes

End'
END
GO




Test Data

CREATE TABLE #T(A INT IDENTITY PRIMARY KEY, B INT , F CHAR(8000) NULL);

INSERT INTO #T(B)
SELECT TOP (900000)  0 + CAST(NEWID() AS BINARY(4))
FROM master..spt_values v1,
     master..spt_values v2;

Performance Monitor


You can use the following performance counters to identify I/O bottlenecks. Note, these AVG values tend to be skewed (to the low side) if you have an infrequent collection interval. For example, it is hard to tell the nature of an I/O spike with 60-second snapshots. Also, you should not rely on one counter to determine a bottleneck; look for multiple counters to cross check the validity of your findings.
  • PhysicalDisk Object: Avg. Disk Queue Length represents the average number of physical read and write requests that were queued on the selected physical disk during the sampling period. If your I/O system is overloaded, more read/write operations will be waiting. If your disk queue length frequently exceeds a value of 2 during peak usage of SQL Server, then you might have an I/O bottleneck.
  • Avg. Disk Sec/Read is the average time, in seconds, of a read of data from the disk. Any number
·       Less than 10 ms - very good
·       Between 10 - 20 ms - okay
·       Between 20 - 50 ms - slow, needs attention
·       Greater than 50 ms – Serious I/O bottleneck
  • Avg. Disk Sec/Write is the average time, in seconds, of a write of data to the disk. Please refer to the guideline in the previous bullet.
  • Physical Disk: %Disk Time is the percentage of elapsed time that the selected disk drive was busy servicing read or write requests. A general guideline is that if this value is greater than 50 percent, it represents an I/O bottleneck.
  • Avg. Disk Reads/Sec is the rate of read operations on the disk. You need to make sure that this number is less than 85 percent of the disk capacity. The disk access time increases exponentially beyond 85 percent capacity.
  • Avg. Disk Writes/Sec is the rate of write operations on the disk. Make sure that this number is less than 85 percent of the disk capacity. The disk access time increases exponentially beyond 85 percent capacity.
When using above counters, you may need to adjust the values for RAID configurations using the following formulas.
Raid 0 -- I/Os per disk = (reads + writes) / number of disks
Raid 1 -- I/Os per disk = [reads + (2 * writes)] / 2
Raid 5 -- I/Os per disk = [reads + (4 * writes)] / number of disks
Raid 10 -- I/Os per disk = [reads + (2 * writes)] / number of disks
For example, you have a RAID-1 system with two physical disks with the following values of the counters.
Disk Reads/sec            80
Disk Writes/sec           70
Avg. Disk Queue Length    5
In that case, you are encountering (80 + (2 * 70))/2 = 110 I/Os per disk and your disk queue length = 5/2 = 2.5 which indicates a border line I/O bottleneck.


Link : 


PerfMonitor Screenshot 















Import Disk Latency Perfmon counters (CSV comma separated values) in to SQL Databases.

  Create table PerfAnalysis
  (
  Dateupdated varchar(255),
  [% Disk Time] varchar(255),
  [Avg. Disk Queue Length] varchar(255),
  [Avg. Disk sec/Read] varchar(255),
  [Avg. Disk sec/Write] varchar(255),
 [Disk Reads/sec] varchar(255),
  [Disk Writes/sec] nvarchar(255)
    )
    
    
     BULK INSERT PerfAnalysis
   FROM 'K:\DataCollector01.csv'
   WITH
      (
         FIELDTERMINATOR =',',
         ROWTERMINATOR ='\n'
      );
     

 select * from PerfAnalysis







No comments:

Post a Comment