Expert 诊断优化系列------------------透过等待看系统
上一篇我们简单的介绍了,语句优化的三板斧,大部分语句三板斧过后,就算不成为法拉利也能是个宝马了。为了方便阅读给出系列文章的导读链接:
SQL SERVER全面优化-------Expert for SQL Server 诊断系列
本篇主要讲述几个常见的系统等待,透过这些等待,看看系统存在什么问题,怎么样解决这些问题。结合系统三巨头(CPU,内存,磁盘)综合展现系统问题和这些元素的联系。
首先我们举个例子:前文提到了,一个好的SQL语句就好比一辆时速180的好车,好的系统硬件(CPU,内存,磁盘)就好比平坦宽阔的马路。看似好车配好路,一定可以开的很快了!其实还忽略了一点!当你驾驶一辆法拉利跑在北京宽阔的三环上,就算你是老炮中的“三环十二少“,早高峰你能开到多少? 北京的早高峰!北京的早高峰!
这个例子就引出了系统阻塞和等待的概念,红灯(硬件等待,如IO等待),这就是正常的等待。另外一辆车在你前面不走了或开的很慢,那么你也只能等待(也可以说成你被他阻塞了)!
--------------博客地址---------------------------------------------------------------------------------------
Expert 诊断优化系列 http://www.cnblogs.com/double-K/
废话不多说,直接开整-----------------------------------------------------------------------------------------
如何判断任务或语句是否在等待?
SQL SERVER所有任务的状态大致有三类(sleeping、runnable或running)通过英文我想不用过多解释了。SQL DMV视图提供了以下三个视图详细查询语句的运行状态:
- Sys.dm_exec_requests :返回有关在SQL Server中执行的每个请求的信息,包括当前的等待状态
- Sys.dm_exec_sessions :对于每个通过身份验证的会话都返回相应的一行。此时图是服务器范围的视图。此视图首先可以查到服务器负荷
- Sys.dm_exec_connections : 返回与SQL Server 实例建立的连接有关的信息以及每个连接的详细信息
- sys.dm_os_wait_stats :SQL Server启动以来所有等待状态的等待数和等待时间。这是个累积值。
- 注:常用查看系统等待的语句文章最后奉上
常见的等待类型
- CXPACKET : 当尝试同步查询处理器交换迭代器时出现。如果针对该等待类型的争用成为问题时,可以考虑降低并行度。
- IO_COMPLETION : 在等待 I/O 操作完成时出现。通常,该等待类型表示非数据页 I/O。
- PAGEIOLATCH_ : 在任务等待 I/O 请求中缓冲区的闩锁时发生。
- PAGELATCH_ : 在任务等待不处于 I/O 请求中的缓冲区闩锁时发生。
- LCK_ :等待闩锁时出现。
- ASYNC_NETWORK_IO : 当任务被阻止在网络之后时出现在网络写入中。验证客户端是否正在处理来自服务器的数据。
- OLEDB :当 SQL Server 调用 Microsoft SQL Native Client OLE DB 访问接口时出现。该等待类型不用于同步。而是用于指示调用 OLE DB 访问接口的持续时间
- WRITELOG :等待日志刷新完成时出现。导致日志刷新的常见操作是检查点和事务提交。
注:等待有很多种,这里主要以这八个等待为例,用普通话讲解这八个等待的意义。并结合例子看看不同的等待中能反应出你SQL SERVER 系统中的哪些问题!
CXPACKET
CXPACKET 这个等待可以简单理解成CPU相关的等待,主要发生在并行计划中。由于并行计划需要协同多个task同时工作,那么“协同”分配等等操作的时候出现的就是这个等待,另外当并行使用的多个task其中一个被阻塞,在sys.dm_exec_requests查看wait_type等待类型也会是CXPACKET。详见:sys.dm_os_waiting_tasks 引发的疑问(上)
如果 CXPACKET 在你系统中是最为严重的等待,这时候一般的表现是你的CPU很高。
解决方案:适当调整并行度。具体设置请参见: Expert 诊断优化系列------------------你的CPU高么?
一般建议系统如果超过32个CPU 那么设置成8或者4,如果系统中都是特别短小且频繁的语句建议设置成1(取消语句并行,要慎重真的符合你的场景才好)
并行开销的阀值,主要控制SQL优化器何时选用并行计划,建议默认值,此值设置的越小优化器越容易选择并行计划。
并行度的设置是针对实例级别的设置(2016中可以对单独数据库设置)
IO类
IO_COMPLETION和PAGEIOLATCH_和WRITELOG 这三个等待是最为常见的和磁盘相关的等待。他们的不同点是 IO_COMPLETION 主要针对非数据页 I/O ,如备份操作所需的磁盘交互。PAGEIOLATCH_ 是数据页相关的磁盘等待。WRITELOG 是日志相关。
如果系统中这三个等待是主要等待,说明系统磁盘存在压力或已经成为瓶颈。
这里用PAGEIOLATCH_ 为例进行说明
PAGEIOLATCH_的 官方解释:在任务等待 I/O 请求中缓冲区的闩锁时发生。闩锁请求处于“XX”模式。长时间的等待可能指示磁盘子系统出现问题。
PAGEIOLATCH_的相关等待:
PAGEIOLATCH_DT |
在任务等待 I/O 请求中缓冲区的闩锁时发生。闩锁请求处于“破坏”模式。长时间的等待可能指示磁盘子系统出现问题。 |
PAGEIOLATCH_EX |
在任务等待 I/O 请求中缓冲区的闩锁时发生。闩锁请求处于“独占”模式。长时间的等待可能指示磁盘子系统出现问题。 |
PAGEIOLATCH_KP |
在任务等待 I/O 请求中缓冲区的闩锁时发生。闩锁请求处于“保持”模式。长时间的等待可能指示磁盘子系统出现问题。 |
PAGEIOLATCH_NL |
仅供内部使用。 |
PAGEIOLATCH_SH |
在任务等待 I/O 请求中缓冲区的闩锁时发生。闩锁请求处于“共享”模式。长时间的等待可能指示磁盘子系统出现问题。 |
PAGEIOLATCH_UP |
在任务等待 I/O 请求中缓冲区的闩锁时发生。闩锁请求处于“更新”模式。长时间的等待可能指示磁盘子系统出现问题。 |
- 怎么来理解这个官方解释呢? 首先明确一点,操作系统CPU操作的任何数据都是从内存中读取的,也就是说读取数据要经过这样的一条路:
- 磁盘中 ——> 内存中 ——> 最终使用
这里的PAGEIOLATCH_ 就是发生在, 磁盘中 ——> 内存中
以读取为例:要读取的数据页不在内存中,所以就要去磁盘上读取这部分数据页,去磁盘读取数据的时候就会产生PAGEIOLATCH_的相关等待,如果磁盘压力大,长时间不能反回数据,那么PAGEIOLATCH_的时间也会越长,语句执行的时间也会越长。
注 : 当你的系统出现大量的 PAGEIOLATCH_ 类等待,说明你磁盘可能存在压力(磁盘速度不能满足当前业务需求)或你的内存不够用,不能缓存业务常用数据而经常要与磁盘交互!
磁盘与内存压力的判断,请参见:Expert 诊断优化系列------------------冤枉磁盘了
WRITELOG 和磁盘有关的另一个等待状态,正在等待写日志记录,意味着写入速度也明显跟不上。而速度跟不上一般有两种情况:磁盘压力大响应时间长或真的速度不能满足读写需要。
PAGELATCH_
PAGELATCH_和 上面讲述的PAGEIOLATCH_ 看似很像,但中间少了 IO 这个关键。
- 磁盘中 ——> 内存中 ——> 最终使用
磁盘中——>内存中 的等待为PAGEIOLATCH_ 而 内存中——> 最终使用 的等待为 PAGELATCH_
当数据已经在内存中的时候SQL SERVER 想要使用这个数据页就要给这个数据页加锁,sql server中PAGELATCH_x和PAGEIOLATCH_x解析
- SQL Server没有明显的内存和磁盘瓶颈(恭喜你!)。
- 应用程序发来大量的并发语句在修改同一张表格里的记录,而表格架构设计以及用户业务逻辑使得这些修改都集中在同一个页面,或者数量不多的几个页面上。这些页面有的时候也被称为Hot Page。这样的瓶颈通常只会发生在并发用户比较多的、典型的OLTP系统上。
- 这种瓶颈是无法通过提高硬件配置解决的,只有通过修改表格设计或者业务逻辑,让修改分散到尽可能多的页面上,才能提高并发性能。
高能预警 : 网上很多人介绍过 PAGELATCH_ 等待,但是很少人有提及TempDB造成的 PAGELATCH_(其实也是一种Hot Page),这里简单的看一个例子:
系统中存在大量的 PAGELATCH_UP等待那么是什么成为了Hot Page 呢?为什么说和TempDB有关呢?
等待资源 “2:X:X: ”开头是TempDB,系统中存在大量且高并发的语句使用临时表和表变量,所以引起TEMPDB瓶颈。TempDB的诊断和优化请关注后续文章。
LCK_
上面说的PAGELATCH_和PAGEIOLATCH_LCK_这种就真真的"锁" 了!LCK_类型中的所有很多,如果这种等待在系统中大量存在,可以说明,系统语句间的相互阻塞严重。如大家都知道的当你update一张表的时候,你的select会被阻塞直到update完成。这里就不过多介绍场景了,主要看一下解决此类等待的主要方法:
- 语句优化,让语句执行的更快,减少等待时间。
- 采用批量操作代替循环方式。
- 尽量减少事务的长度。
- 上述都不能缓解...请选用读写分离。
LCK_类型中包含:(这里不做详细解读了)
LCK_M_RIn_NL |
当某任务正在等待获取当前键值上的 NULL 锁以及当前键和上一个键之间的插入范围锁时出现。键上的 NULL 锁是指立即释放的锁。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RIn_S |
当某任务正在等待获取当前键值上的共享锁以及当前键和上一个键之间的插入范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RIn_U |
任务正在等待获取当前键值上的更新锁以及当前键和上一个键之间的插入范围锁。有关锁兼容性矩阵,请参阅sys.dm_tran_locks。 |
LCK_M_RIn_X |
当某任务正在等待获取当前键值上的排他锁以及当前键和上一个键之间的插入范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RS_S |
当某任务正在等待获取当前键值上的共享锁以及当前键和上一个键之间的共享范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RS_U |
当某任务正在等待获取当前键值上的更新锁以及当前键和上一个键之间的更新范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RX_S |
当某任务正在等待获取当前键值上的共享锁以及当前键和上一个键之间的排他范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RX_U |
当某任务正在等待获取当前键值上的更新锁以及当前键和上一个键之间的排他范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_RX_X |
当某任务正在等待获取当前键值上的排他锁以及当前键和上一个键之间的排他范围锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_S |
当某任务正在等待获取共享锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_SCH_M |
当某任务正在等待获取架构修改锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_SCH_S |
当某任务正在等待获取架构共享锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_SIU |
当某任务正在等待获取共享意向更新锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_SIX |
当某任务正在等待获取共享意向排他锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_U |
当某任务正在等待获取更新锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_UIX |
当某任务正在等待获取更新意向排他锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
LCK_M_X |
当某任务正在等待获取排他锁时出现。有关锁兼容性矩阵,请参阅 sys.dm_tran_locks。 |
ASYNC_NETWORK_IO
此等待状态出现在SQLServer已经把数据准备好,但是网络没有足够的发送速度跟上,所以SQLServer的数据没地方存放。
- 出现这种情况一般不是数据库的问题,调整数据库配置不会有大的帮助。
- 网络层的瓶颈当然是一个可能的原因:对此要考虑是否真有必要返回那么多数据?
- 应用程序端的性能问题,也会导致SQLServer里的ASYNC_NETWORK_IO等待。如果见到了这个类型的等待,就要检查应用程序的健康状况,也要检查应用是否有必要想SQLServer申请这么大的结果集。
- 程序返回结果集的方式 : 详见 select * from table 时间长
--------------博客地址---------------------------------------------------------------------------------------
Expert 诊断优化系列 http://www.cnblogs.com/double-K/
-----------------------------------------------------------------------------------------------------
总结:系统等待往往能直接反应出系统问题。本文主要介绍了 CXPACKET —— CPU,PAGEIOLATCH_ —— 磁盘、内存的联系。
等待是系统中不能避免的,但通过语句优化,结构设计优化都能缓解这些阻塞。
语句的慢和等待有着密不可分的联系。
出现CXPACKET 一般考虑降低并行度,PAGEIOLATCH_ 一般考虑内存和磁盘(一般情况语句优化可以解决),WRITELOG 一般意味着写入速度跟不上(如果程序对磁盘的冲击已经降到最小还是跟不上,那么才意味着你需要更好的硬件了)。
-------------------------干货到了--------------------------------------------------------------------------
运行语句监控(非常好用哦~)
WITH sess AS
(
SELECT
es.session_id,
database_name = DB_NAME(er.database_id),
er.cpu_time,
er.reads,
er.writes,
er.logical_reads,
login_name,
er.status,
blocking_session_id,
wait_type,
wait_resource,
wait_time,
individual_query = SUBSTRING (qt.text, (er.statement_start_offset/2)+1, ((CASE WHEN er.statement_end_offset = -1 THEN LEN(CONVERT(NVARCHAR(MAX), qt.text)) * 2 ELSE er.statement_end_offset END - er.statement_start_offset)/2)+1),
parent_query = qt.text,
program_name,
host_name,
nt_domain,
start_time,
DATEDIFF(MS,er.start_time,GETDATE()) as duration,
(SELECT query_plan FROM sys.dm_exec_query_plan(er.plan_handle)) AS query_plan
FROM
sys.dm_exec_requests er
INNER JOIN sys.dm_exec_sessions es ON er.session_id = es.session_id
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle)as qt
WHERE
es.session_id > 50
AND es.session_Id NOT IN (@@SPID)
)
SELECT
*
FROM
sess
UNION ALL SELECT
es.session_id,
database_name = '',
0,
0,
0,
0,
login_name,
es.status,
0,
'',
'',
'',
qt.text,
parent_query = qt.text,
program_name,
host_name,
nt_domain,
es.last_request_start_time,
DATEDIFF(MS,es.last_request_start_time,GETDATE()) as duration,
NULL AS query_plan
FROM
sys.dm_exec_sessions es
INNER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id
CROSS APPLY sys.dm_exec_sql_text(ec.most_recent_sql_handle)as qt
WHERE
ec.most_recent_session_id IN
(
SELECT blocking_session_id FROM sess WHERE blocking_session_id NOT IN(SELECT DISTINCT session_id FROM sess)
)
ORDER BY
1, 2
----------------------------------------------------------------------------------------------------
注:此文章为原创,欢迎转载,请在文章页面明显位置给出此文链接!
若您觉得这篇文章还不错请点击下右下角的推荐,非常感谢!
引用高大侠的一句话 :“拒绝SQL Server背锅,从我做起!”
为了方便阅读给出系列文章的导读链接:
SQL SERVER全面优化-------Expert for SQL Server 诊断系列
Expert 诊断优化系列------------------透过等待看系统的更多相关文章
- Expert 诊断优化系列------------------语句调优三板斧
前面三篇通过CPU.内存.磁盘三巨头,讲述了如何透过现在看本质,怎样定位服务器三巨头反映出的问题.为了方便阅读给出链接: SQL SERVER全面优化-------Expert for SQL Ser ...
- Expert 诊断优化系列------------------给TempDB 降温
前面文章针对CPU.内存.磁盘.语句.等待讲述了SQL SERVER的一些基本的问题诊断与调优方式.为了方便阅读给出导读文章链接方便阅读: SQL SERVER全面优化-------Expert fo ...
- Expert 诊断优化系列------------------锁是个大角色
前面几篇已经陆续从服务器的几个大块讲述了SQL SERVER数据库的诊断和调优方式.加上本篇可以说已经可以完成常规的问题诊断及优化,本篇就是SQL SERVER中的锁.为了方便阅读给出系列文章的导读链 ...
- Expert 诊断优化系列------------------冤枉磁盘了
现在很多用户被数据库的慢的问题所困扰,又苦于花钱请一个专业的DBA成本太高.软件维护人员对数据库的了解又不是那么深入,所以导致问题迟迟不能解决,或只能暂时解决不能得到根治.开发人员解决数据问题基本又是 ...
- Expert 诊断优化系列-------------针对重点语句调索引
上一篇我们说了索引的重要性,一个索引不仅能让一条语句起飞,也能大量减少系统对CPU.内存.磁盘的依赖.我想上一篇中的例子可以说明了.给出上一篇和目录文链接: SQL SERVER全面优化------- ...
- Expert 诊断优化系列------------------内存不够用么?
现在很多用户被数据库的慢的问题所困扰,又苦于花钱请一个专业的DBA成本太高.软件维护人员对数据库的了解又不是那么深入,所以导致问题迟迟不能解决,或只能暂时解决不能得到根治.开发人员解决数据问题基本又是 ...
- Expert 诊断优化系列------------------你的CPU高么?
现在很多用户被数据库的慢的问题所困扰,又苦于花钱请一个专业的DBA成本太高.软件维护人员对数据库的了解又不是那么深入,所以导致问题迟迟不能解决,或只能暂时解决不能得到根治.开发人员解决数据问题基本又是 ...
- 数据库优化案例——————某市中心医院HIS系统
记得在自己学习数据库知识的时候特别喜欢看案例,因为优化的手段是容易掌握的,但是整体的优化思想是很难学会的.这也是为什么自己特别喜欢看案例,今天也开始分享自己做的优化案例. 最近一直很忙,博客产出也少的 ...
- JVM性能优化系列-(2) 垃圾收集器与内存分配策略
2. 垃圾收集器与内存分配策略 垃圾收集(Garbage Collection, GC)是JVM实现里非常重要的一环,JVM成熟的内存动态分配与回收技术使Java(当然还有其他运行在JVM上的语言,如 ...
随机推荐
- 病毒四度升级:安天AVL Team揭露一例跨期两年的电信诈骗进化史
自2014年9月起,安天AVL移动安全团队持续检测到一类基于Android移动平台的间谍类病毒,病毒样本大多伪装成名为"最高人民检察院"的应用.经过反编译逆向分析以及长期的跟踪调查 ...
- [项目]WebService涉及到的部分核心代码
前言: 博客园似乎不太喜欢设计模式的东西,一连写了几篇设计模式的东西,都没什么人气,也许是写的水平有些不够,另外设计模式属于内功,怎们都得修炼一下,否则,设计混乱,不成体系,对于大型项目来说,就会显 ...
- linux作业
第二单元 (1)以root用户登录GNOME图形界面 语言支持选择为汉语 (2)使用快捷键切换到虚拟终端2,使用普通用户身份登录,查看系统提示符 (3)使用命令退出虚拟终端2上登录的用户 (4)使用快 ...
- Java基础学习(四)
流程控制 /* 控制流程语句之---if 判断语句 格式一: 只适用于一种情况下去使用. if(判断条件){ 符合条件执行的代码; } 格式二:适用于两种情况下去使用 if(判断条件){ 符合条件执行 ...
- grafana
metrics+grafana elk 这两套系统居家旅游必备啊
- windows和linux平台下的通用时间测试函数
Time.cpp ////////////////////////////////////////////////////////////////////////////// // Timer.cpp ...
- 运用泛型,冒泡排序实现JDK引用类型数组的排序
public class Utils { public static <T extends Comparable<T>> void sortList(List<T> ...
- Android获取ImageView上的图片,和一个有可能遇到的问题!
1.在获取图片前先调用setDrawingCacheEnabled(true)这个方法: 举例:mImageView.setDrawingCacheEnabled(true); 2.之后可以通过get ...
- 【vuejs小项目——vuejs2.0版本】组件化的开发方式
对于多张页面需要里存在相同模块,可以进行组建化的开发模式. 例如:此处需要一个评分标准组件,创建一个components/star/star.vue. 在需要引入该组建的页面上 import进去< ...
- ehcache注解全面解析---打酱油的日子
通过ehcache以编程方式使用缓存: 跟上面的方式相同,但是缓存通过ehcache去管理,当然比使用map有N多种好处,比如缓存太大了快达到上限之后,将哪一部分缓存清除出去.这种方式完全是通过代码的 ...