Resolving SQL Server Disk IO bottlenecks
网上看到这篇文章挺不错的,直接翻译过来。
在尝试诊断SQL Server性能时,不要仅仅依赖某个单一的诊断数据,比如CPU的使用率、SQL Server磁盘性能,就得出结论却忽略的问题的根源。实际上,使用单一的度量经常会得出一个错误的诊断。
在SQL Server中CPU、IO和内存的使用是相互依赖。在我们采取"knee-jerk"修正行动(添加内存、提升磁盘吞吐量或者更改配置设置)之前,我们需要先查看整体情况。
一、服务器级别
"进程X运行缓慢,你能修复它吗?"
作为DBA,你决定打开资源监视器(resmon),发现磁盘活动异常
在性能监视器(perfmon)查看部分磁盘相关的计数器
伴随着磁盘请求队列的平均长度急剧上升,从磁盘读取数据存在较高的延迟。好像磁盘子系统成为一个瓶颈,它正努力跟上请求数量,SQL Server磁盘IO性能恶化,队列形成。
你应该采取什么行动解决这个问题呢?在你打算联系系统管理员去看是否可以做些什么来提升磁盘能力,你最好是再深入挖掘下。
如果你只关注一个特定的性能指标,很容易对SQL Server性能问题进行误诊。
你可能有证据表明存在一个特定的瓶颈,但是在本例SQL Server磁盘IO,把磁盘性能不够或者磁盘子系统配置当成问题的根源就有点危险了。
The excessive disk IO could easily have its root cause elsewhere.你需要收集更多的数据来确认问题的根源。但是,你从哪里开始呢?
二、深入挖掘
2.1、Wait statistics
一个好的开始是分析SQL Server等待统计,它通常能够表明为什么SQL Server会话在获取所需资源以执行请求前被迫暂停处理(等待)。通过分析等待,我们可以识别繁忙的服务器上主要引起争用的资源。
查询sys.dm_os_waiting_tasks动态管理视图(DMV),显示所有正在等待资源执行的语句,可以关联其他DMVs得到相关会话和请求的详细信息。作为演示,我们执行以下脚本
--Analyze the queries that are currently running or which have recently ran and their plan is still in the cache.
SELECT dm_ws.wait_duration_ms,
dm_ws.wait_type,
dm_es.status,
dm_t.TEXT,
dm_qp.query_plan,
dm_ws.session_ID,
dm_es.cpu_time,
dm_es.memory_usage,
dm_es.logical_reads,
dm_es.total_elapsed_time,
dm_es.program_name,
DB_NAME(dm_r.database_id) DatabaseName,
-- Optional columns
dm_ws.blocking_session_id,
dm_r.wait_resource,
dm_es.login_name,
dm_r.command,
dm_r.last_wait_type
FROM sys.dm_os_waiting_tasks dm_ws
INNER JOIN sys.dm_exec_requests dm_r ON dm_ws.session_id = dm_r.session_id
INNER JOIN sys.dm_exec_sessions dm_es ON dm_es.session_id = dm_r.session_id
CROSS APPLY sys.dm_exec_sql_text (dm_r.sql_handle) dm_t
CROSS APPLY sys.dm_exec_query_plan (dm_r.plan_handle) dm_qp
WHERE dm_es.is_user_process = 1
GO
--You can change CROSS APPLY to OUTER APPLY if you want to see all the details which are omitted because of the plan cache
我们看到两个等待类型,以及相关的查询文本和计划
当然,我们经常对一个问题进行回顾性调查,这样前面的DMV就没太大的用处。作为替换,我们可以查询sys.dm_os_wait_stats动态管理视图,它包含所有等待类型的"运行总值",自上次服务重启或者我们使用DBCC SQLPERF命令手动重置统计信息以来所有请求的累积值
--All wait types since the server was last restarted, or the statistics were manually reset
WITH [Waits] AS
(SELECT
[wait_type],
[wait_time_ms] / 1000.0 AS [WaitS],
([wait_time_ms] - [signal_wait_time_ms]) / 1000.0 AS [ResourceS],
[signal_wait_time_ms] / 1000.0 AS [SignalS],
[waiting_tasks_count] AS [WaitCount],
100.0 * [wait_time_ms] / SUM ([wait_time_ms]) OVER() AS [Percentage],
ROW_NUMBER() OVER(ORDER BY [wait_time_ms] DESC) AS [RowNum]
FROM sys.dm_os_wait_stats
WHERE [wait_type] NOT IN (
N'BROKER_EVENTHANDLER', N'BROKER_RECEIVE_WAITFOR',
N'BROKER_TASK_STOP', N'BROKER_TO_FLUSH',
N'BROKER_TRANSMITTER', N'CHECKPOINT_QUEUE',
N'CHKPT', N'CLR_AUTO_EVENT',
N'CLR_MANUAL_EVENT', N'CLR_SEMAPHORE', -- Maybe uncomment these four if you have mirroring issues
N'DBMIRROR_DBM_EVENT', N'DBMIRROR_EVENTS_QUEUE',
N'DBMIRROR_WORKER_QUEUE', N'DBMIRRORING_CMD', N'DIRTY_PAGE_POLL', N'DISPATCHER_QUEUE_SEMAPHORE',
N'EXECSYNC', N'FSAGENT',
N'FT_IFTS_SCHEDULER_IDLE_WAIT', N'FT_IFTSHC_MUTEX', -- Maybe uncomment these six if you have AG issues
N'HADR_CLUSAPI_CALL', N'HADR_FILESTREAM_IOMGR_IOCOMPLETION',
N'HADR_LOGCAPTURE_WAIT', N'HADR_NOTIFICATION_DEQUEUE',
N'HADR_TIMER_TASK', N'HADR_WORK_QUEUE', N'KSOURCE_WAKEUP', N'LAZYWRITER_SLEEP',
N'LOGMGR_QUEUE', N'MEMORY_ALLOCATION_EXT',
N'ONDEMAND_TASK_QUEUE',
N'PREEMPTIVE_XE_GETTARGETSTATE',
N'PWAIT_ALL_COMPONENTS_INITIALIZED',
N'PWAIT_DIRECTLOGCONSUMER_GETNEXT',
N'QDS_PERSIST_TASK_MAIN_LOOP_SLEEP', N'QDS_ASYNC_QUEUE',
N'QDS_CLEANUP_STALE_QUERIES_TASK_MAIN_LOOP_SLEEP',
N'QDS_SHUTDOWN_QUEUE', N'REDO_THREAD_PENDING_WORK',
N'REQUEST_FOR_DEADLOCK_SEARCH', N'RESOURCE_QUEUE',
N'SERVER_IDLE_CHECK', N'SLEEP_BPOOL_FLUSH',
N'SLEEP_DBSTARTUP', N'SLEEP_DCOMSTARTUP',
N'SLEEP_MASTERDBREADY', N'SLEEP_MASTERMDREADY',
N'SLEEP_MASTERUPGRADED', N'SLEEP_MSDBSTARTUP',
N'SLEEP_SYSTEMTASK', N'SLEEP_TASK',
N'SLEEP_TEMPDBSTARTUP', N'SNI_HTTP_ACCEPT',
N'SP_SERVER_DIAGNOSTICS_SLEEP', N'SQLTRACE_BUFFER_FLUSH',
N'SQLTRACE_INCREMENTAL_FLUSH_SLEEP',
N'SQLTRACE_WAIT_ENTRIES', N'WAIT_FOR_RESULTS',
N'WAITFOR', N'WAITFOR_TASKSHUTDOWN',
N'WAIT_XTP_RECOVERY',
N'WAIT_XTP_HOST_WAIT', N'WAIT_XTP_OFFLINE_CKPT_NEW_LOG',
N'WAIT_XTP_CKPT_CLOSE', N'XE_DISPATCHER_JOIN',
N'XE_DISPATCHER_WAIT', N'XE_TIMER_EVENT')
AND [waiting_tasks_count] > 0
)
SELECT
MAX ([W1].[wait_type]) AS [WaitType],
CAST (MAX ([W1].[WaitS]) AS DECIMAL (16,2)) AS [Wait_S],
CAST (MAX ([W1].[ResourceS]) AS DECIMAL (16,2)) AS [Resource_S],
CAST (MAX ([W1].[SignalS]) AS DECIMAL (16,2)) AS [Signal_S],
MAX ([W1].[WaitCount]) AS [WaitCount],
CAST (MAX ([W1].[Percentage]) AS DECIMAL (5,2)) AS [Percentage],
CAST ((MAX ([W1].[WaitS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgWait_S],
CAST ((MAX ([W1].[ResourceS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgRes_S],
CAST ((MAX ([W1].[SignalS]) / MAX ([W1].[WaitCount])) AS DECIMAL (16,4)) AS [AvgSig_S],
CAST ('https://www.sqlskills.com/help/waits/' + MAX ([W1].[wait_type]) as XML) AS [Help/Info URL]
FROM [Waits] AS [W1]
INNER JOIN [Waits] AS [W2]
ON [W2].[RowNum] <= [W1].[RowNum]
GROUP BY [W1].[RowNum]
HAVING SUM ([W2].[Percentage]) - MAX( [W1].[Percentage] ) < 95; -- percentage threshold
GO
重置sys.dm_os_wait_stats统计信息
-- reset statistics
DBCC SQLPERF (N'sys.dm_os_wait_stats', CLEAR);
GO
当前查询的两个最贵的等待类型ASYNC_NETWORK_IO和PAGEIOLATCH_SH也出现在这里。如果我们调查的问题不是一个经常性或长期存在的问题,那么有可能相关的等待类型将被"淹没"在历史的等待之中。这就是为什么维护等待统计基线是很重要的。
ASYNC_NETWORK_IO等待类型是一个网络相关的等待,表明客户端不能足够快地处理数据(例子中的查询重重执行并返回大量数据给SSMS)。In general, watch out for this wait type as a warning of inefficient data processing on the client-side.
例子中更有趣的是PAGEIOLATCH_SH等待类型,意味着查询请求必须等待一个latch,以便从磁盘中读取没有保存在buffer cache中的数据。这似乎加强了我们最初的直觉,问题在磁盘供电或错误的配置上。如果磁盘子系统无法快速返回页面,那么它可能会导致更长的请求等待队列来获取页面,以及latch争用。
然而,如果我们怀疑磁盘瓶颈,什么是根本原因?一个有用的下一步是找出更多的IO负载。比如,磁盘活动是否有特别的数据库和数据库文件"热点"?
2.2、Virtual file statistics
通过查询sys.dm_io_virtual_file_stats动态管理视图我们可以知道文件使用统计信息。使用如下脚本
-- Get I/O utilization by database (Query 31) (IO Usage By Database)
WITH Aggregate_IO_Statistics
AS
(SELECT DB_NAME(database_id) AS [Database Name],
CAST(SUM(num_of_bytes_read + num_of_bytes_written)/1048576 AS DECIMAL(12, 2)) AS io_in_mb
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS [DM_IO_STATS]
GROUP BY database_id)
SELECT ROW_NUMBER() OVER(ORDER BY io_in_mb DESC) AS [I/O Rank], [Database Name], io_in_mb AS [Total I/O (MB)],
CAST(io_in_mb/ SUM(io_in_mb) OVER() * 100.0 AS DECIMAL(5,2)) AS [I/O Percent]
FROM Aggregate_IO_Statistics
ORDER BY [I/O Rank] OPTION (RECOMPILE);
-- Helps determine which database is using the most I/O resources on the instance
它提供洞察数据库实例上的IO活动,特别是用于揭示IO负载是否分布在不同的数据库
上图显示SQLMonTest数据库是IO热点。同样,这些统计数据是自服务上次启动以来的累积值,但不同于等待统计,不能手动重置(The DMF contains cumulative I/O information for each database file. The DMF data get reset on the instance restart, database offline, detached and reattached activities.)。下面的脚本能够明确的显示相关数据库的高读和写延迟。AdventureWorks2014和SQLMonTest出现在列表的前面
-- 下面的查询返回哪个数据库文件有最大的I/O延迟
-- Calculates average stalls per read, per write,
-- and per total input/output for each database file.
SELECT DB_NAME(fs.database_id) AS [database_name],
mf.physical_name,
CONVERT(DECIMAL(18, 2), mf.size / 128.0) AS [file_size_mb],
io_stall_read_ms,
num_of_reads,
CAST(io_stall_read_ms / (1.0 + num_of_reads) AS NUMERIC(10, 1)) AS [avg_read_stall_ms],
io_stall_write_ms,
num_of_writes,
CAST(io_stall_write_ms / (1.0 + num_of_writes) AS NUMERIC(10, 1)) AS [avg_write_stall_ms],
io_stall_read_ms + io_stall_write_ms AS [io_stalls],
num_of_reads + num_of_writes AS [total_io],
CAST((io_stall_read_ms + io_stall_write_ms) / (1.0 + num_of_reads + num_of_writes) AS NUMERIC(10, 1)) AS [avg_io_stall_ms]
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS fs
INNER JOIN sys.master_files AS mf WITH (NOLOCK)
ON fs.database_id = mf.database_id
AND fs.[file_id] = mf.[file_id]
ORDER BY avg_io_stall_ms DESC OPTION(RECOMPILE);
-- Helps determine which database files on
-- the entire instance have the most I/O bottlenecks
I/O Latency
2.3、Query execution statistics
已经把问题缩小到一个或两个数据库,下一个逻辑问题是:哪些请求引起数据库上的IO活动?我们可以检查sys.dm_exec_query_stats中的查询执行统计信息。我们可以使用下面的脚本得到指定数据库中总物理读最高的查询以及相关的plan handles(输出结果的部分列省略)
SELECT TOP 10
t.text ,
execution_count ,
statement_start_offset AS stmt_start_offset ,
sql_handle ,
plan_handle ,
total_logical_reads / execution_count AS avg_logical_reads ,
total_logical_writes / execution_count AS avg_logical_writes ,
total_physical_reads / execution_count AS avg_physical_reads,t.dbid
FROM sys.dm_exec_query_stats AS s
CROSS APPLY sys.dm_exec_sql_text(s.sql_handle) AS t
--WHERE DB_NAME(t.dbid) = 'AdventureWorks2008R2'
ORDER BY avg_physical_reads DESC;
我们可以将结果中的plan_handle代入sys.dm_exec_query_plan得到查询的执行计划,再去分析是否存在潜在问题。
总结
通过整体审查所有相关的性能指标,我们有最好的机会选择最有效的行动。在本例中,很明显最初的努力方向应该是查询优化和索引策略,因为我们的查询没有WHERE筛选,导致SQL Server执行整表联接。过度的页面读取导致"缓存流失",SQL Server刷新缓冲页到磁盘用于容纳新页,其后果就是"磁盘瓶颈",and sessions waiting to obtain buffer cache latches on pages that need to be read from disk.
Resolving SQL Server Disk IO bottlenecks的更多相关文章
- Performance Monitor4:监控SQL Server的IO性能
SQL Server的IO性能受到物理Disk的IO延迟和SQL Server内部执行的IO操作的影响.在监控Disk性能时,最主要的度量值(metric)是IO延迟,IO延迟是指从Applicati ...
- 虚拟机备份克隆导致SQL SERVER 出现IO错误案例
案例环境: 服务器配置: CPU: Intel E5-2690 RAM: 12G 虚拟机 操作系统 : Windows Server 2008 R2 Standard Edtion ...
- VITAM POST MORTEM – ANALYZING DEADLOCKED SCHEDULERS MINI DUMP FROM SQL SERVER
https://gennadny.wordpress.com/2014/11/ Since SQL Server 7.0, SQL Server has its own scheduling mech ...
- SQL Server 服务器磁盘测试之SQLIO篇(一)
数据库调优工作中,有一部分是需要排查IO问题的,例如IO的速度或者RAID级别无法响应高并发下的快速请求.最常见的就是查看磁盘每次读写的响应速度,通过性能计数器Avg.Disk sec/Read(Wr ...
- Disk IO Performance
一,使用 Performance counter 监控Disk IO问题 1,Physical Disk vs. Logical Disk Windows可以在一个Physical Disk上划出若干 ...
- 转载 50种方法优化SQL Server数据库查询
原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...
- SQL Server 服务器磁盘测试之SQLIO篇
原文:SQL Server 服务器磁盘测试之SQLIO篇 数据库调优工作中,有一部分是需要排查IO问题的,例如IO的速度或者RAID级别无法响应高并发下的快速请求.最常见的就是查看磁盘每次读写的响应速 ...
- SQL Server 服务器磁盘测试之SQLIO篇(二)
上次放出了一篇文章,针对磁盘卷簇大小默认4KB和自定义64KB进行了测试,测试内容为随机和顺序读写,大小为8KB和64KB,有人觉得这并没有照顾到SQL Server所有的IO使用情景.这篇测试文章, ...
- SQL Server索引进阶:第四级,页和区
原文地址: Stairway to SQL Server Indexes: Level 4, Pages and Extents 本文是SQL Server索引进阶系列(Stairway to SQL ...
随机推荐
- [译]:Orchard入门——手动安装Orchard
原文链接:Manually Installing Orchard 文章内容基于Orchard 1.8版本 本文将演示通过zip安装包安装Orchard所需要的步骤. 本文包括如下三种不同的Orchar ...
- java中的继承与oc中的继承的区别
为什么要使用继承? 继承的好处: (1)抽取出了重复的代码,使代码更加灵活 (2)建立了类和类之间的联系 继承的缺点: 耦合性太强 OC中的继承 1.OC中不允许子类和父类拥有相同名称的成员变量名:( ...
- sd卡脱机烧写系统的方法(测试成功)
一.sd卡烧写系统的基本思路: (1)把uboot.bin烧写到sd卡 (2)把image整个文件夹复制到sd卡 (3)开发板从sd卡启动,就开始自动烧写到nandflash中了. 二.烧写uboot ...
- ios 模拟器内部网络连接问题
今日,一运行程序,打印出来头疼的的日志 "Error Domain=kCFErrorDomainCFNetwork Code=-1001 "The request timed ou ...
- matlab学习第一天
>> x=linspace(-,,); >> y=x.^.*sin(x); >> plot(x,y,) >> plot(x,y,) 分析: linspa ...
- 2016 Multi-University Training Contest 6
5/12 2016 Multi-University Training Contest 6 官方题解 打表找规律/推公式 A A Boring Question(BH) 题意: ,意思就是在[0,n] ...
- Apple Pay--iOS开发
一.什么是Apple Pay? 1. 概念 Apple Pay,简单来说, 就是一种移动支付方式.通过Touch ID/ Passcode,用户可使用存储在iPhone 6, 6p等设备上的信用卡和借 ...
- Hadoop生态圈
1.Hadoop是什么? 适合大数据的分布式存储与计算平台 HDFS: Hadoop Distributed File System分布式文件系统 MapReduce:并行计算框架 解决的问题: HD ...
- CSS3初学篇章_7(布局/浏览器默认样式重置)
CSS布局说到布局,就不得不提布局的核心<div>标签,它与其它标签一样,也是一个XHTML所支持的标签,专门用于布局设计的容器标签.在css布局方式中,div 是这种布局方式的核心对象, ...
- 如何完全卸载oracle11g?
步骤一: 停止Oracle的所有服务. 步骤二: 运行%oracle_home%\app\Administrator\product\11.2.0\dbhome_1\deinstall \deinst ...