Sql Server 内存相关计数器以及内存压力诊断

  在数据库服务器中,内存是数据库对外提供服务最重要的资源之一,
  不只仅是Sql Server,包括其余数据库,好比Oracle,MySQL等,都是一类很是喜欢内存的应用.
  在Sql Server服务器中,最理想的状况是Sql Server把全部所需的数据所有缓存到内存中,可是这每每也是不现实的,由于数据每每老是大于可用的物理内存
  能够说内存是否存在压力可以直接决定数据库可否高效运行,
  同时,若是内存出现压力,同时也会影响到CPU的使用和存储性能,能够说是一损俱损,具备连带性。
  那么,如何识别内存是否存在压力,如何判断一台服务器上是否存在内存瓶颈?html

 

  Sql Server 2012以后,对内存的管理进行了大刀阔斧的改革,全部的内存管理都受Max Server Memory的控制
  以下截图所示的最大服务器内存设置(固然这个截图是我本机上一个测试实例,这里并不说明内存该怎么配置)
算法

而大多数的内存量化都涉及到Sql Server的Buffer Pool,一个内部的缓存管理器,sql

 

/*
  20160525补充:
  Sql Server 2012以前的版本,
  对于Buffer Pool是存储Data Cache的,
  另一部分专用的内存称之为Memory To Leave(Sql Server 2012以后,叫作Stolen Memory),
  这部份内存的使用也是一个很是大的话题,这里暂不展开论述。
  32位操做系统下,这部份内存是Sql Server 启动后直接初始化分配的,64位操做系统是直接跟操做系统申请,
  若是须要的Stolen Memory过大,一样会“挤压”Buffer Pool的内存
*/数据库

 

  可是,Sql Server2012以后,全部内存的管理都受到Max Server Memory的控制。
  同时,Sql Server在运行的过程当中,会将各类内存的参数状况记录下来,这对咱们去判断Sql Server内存压力有着很是重要的参考意义
  下面提到的部分计数器的就存储在sys.dm_os_performance_counters这个系统视图中windows

 

 

咱们抽取其中最重要的几个来作解释说明:缓存

  1. Page Life Expectancy
  2. Buffer Cache hit ratio
  3. Page reads / sec
  4. Page writes / sec
  5. Lazy writes / sec
  6. Total Server Memory
  7. Target Server Memory
  8. Paging File % Usage

须要注意的是,不能经过上述某一个值就武断地判定内存瓶颈,各个计数器之间是有必定的关系的,要结合多个值来作谨慎的分析判断。服务器

 

 

  • Page Life Expectancy

  Page Life Expectancy又简称位PLE,含义是内存页面在内存中停留的平均时间,是内存压力判断的一个重要参考值
  在系统视图sys.dm_os_performance_counters中能够查到,单位是秒.
  须要注意的是它不是指某一个page的最大值或者最小值,而是全部由全部页面停留在buffer pool中的时间计算出来的一个平均值
  若是这个值越大,说明Sql Server在检索数据时候直接从buffer pool中获取数据的几率越大,
  若是Sql Server直接从buffer pool中检索到数据,那么就不用去磁盘中去查询,由于直接从内存中获取数据的效率要远远高出从磁盘中去获取数据
  由于从内存中查询数据的延迟是纳秒级的,而从磁盘获取数据的延迟是毫秒级的,这之间差了两个数量级,
  可见从缓存中获取数据和从磁盘中获取数据,对性能的影响有多大
  那么PLE这个值多少位正常呢?我发现不少资料上多这个值都有误解,说是300S,300S是在十多年前的一个参考值,
  是基于当时的服务器内存受到4GB内存的限制的影响获得的,
  目前服务器内存动辄超过100GB的状况下,用一样的标准,显然是不够准确的,这个值的计算是跟具体的服务器内存配置有关的
  具体我就不作进一步的解释,能够参考以下连接sqlserver

  https://simplesqlserver.com/2013/08/19/fixing-page-life-expectancy-ple/性能

    一个可供参考的标准算法是 Max Buffer Pool(GB)/4*300(S)
    这个值能够经过sys.dm_os_performance_counters 这个系统视图直接查询得出学习

select * 
from sys.dm_os_performance_counters 
where object_name like '%Buffer Manager%' and counter_name='Page life expectancy'

    好比你的服务内存是64G,分配给Sql Server最大内存(上述Max Server Memory)是60G
    那么PLE的参考值就是60/4*300=4500S,大概是75分钟,也就是说,最低限度是每75分钟,内存中的数据跟磁盘作一次完整的交换
    若是你的服务器上的PLE值长期低于计算出来的这个参考值,或者这个值在某个时间段内有很是明显的变化,那么你就须要注意内存是否存在瓶颈了
    若是你真的作过这方面观察的话,这个值在不一样环境中差异是很是大的
    固然对于测试服务器,常常没几我的用,或者压力很是小的服务器,内存没压力或者服务器根本没有负载的状况下,缓存进去的数据可能就一直存在于内存中
    这个值有可能很是大,达到几万秒都是有可能的
    不信我给你截个图,呵呵

  

    固然对于压力比较大的生产服务器,即使是有几十个GB的内存,这个值,也有可能小到几十秒钟,我所在的公司就是这个状况。
    因此,PLE的值是做为判断内存是否存在瓶颈的最重要的指标之一。

 

  • Buffer Cache hit ratio

    Buffer Cache hit ratio就是缓存命中率,字面上的解释就是一个查询过程当中所须要的时候,直接从内存中读取出来的比例占全部数据的百分比
    鉴于表现出来的值受到其算法的制约,反却是在内存压力诊断的时候并不具有太多的参考意义,
    既然Buffer Cache hit ratio不具有太多的参考意思,那么为何把他放在这里呢?
    由于这一个很是流行的参数,不少材料上都提到过这个参数
    不少材料上都介绍其阈值是90%,95%之类的参考值,其实都是错误的,
    其实真正观察过的人,以下连接,早就有人有此疑问了,从PLE和Buffer hit ratio得出根本不一致的结论,
    有时候咱们作学问仍是要讲究严禁的,不能人云亦云

    怎样理解Buffer hit ratio 是99%, 但Page life expectancy<200?

    我这里不作详述,能够参考个人另外一篇博文,里面有详述。http://www.cnblogs.com/wy123/p/5272675.html

    另外,真的很佩服老外,从本质上阐述了Buffer Cache hit ratio,能把学问作的这么认真,真的不容易。

经过sql查询缓存命中率

SELECT 
  CAST(CAST((a.cntr_value * 1.0 / b.cntr_value)*100 as int) AS VARCHAR(20)) as BufferCacheHitRatio
FROM (
        SELECT * FROM sys.dm_os_performance_counters
        WHERE counter_name = 'Buffer cache hit ratio'
        AND object_name = CASE WHEN @@SERVICENAME = 'MSSQLSERVER'
        THEN 'SQLServer:Buffer Manager'
        ELSE 'MSSQL$' + rtrim(@@SERVICENAME) +
        ':Buffer Manager' END 
    ) a
CROSS JOIN
(
    SELECT * from sys.dm_os_performance_counters
    WHERE counter_name = 'Buffer cache hit ratio base'
    and object_name = CASE WHEN @@SERVICENAME = 'MSSQLSERVER'
    THEN 'SQLServer:Buffer Manager'
    ELSE 'MSSQL$' + rtrim(@@SERVICENAME) +
    ':Buffer Manager' END 
) b

 

 

  • Page reads(writes) / sec 

  这两个计数器分别是对应的平均每秒钟的物理读/写的数据量,这个计数器的是一个累计值,单位为page,而每一个page又是8Kb,
  能够换算成一个基于kb或者mb位单位数据
  对于计数器中的相似累计值,并不妨碍咱们经过计算得出某个时间间隔内的平均值。
  也就是说,
  对于 Page reads / sec,一个查询在执行过程当中,发现须要的数据不存在于buffer pool中,须要到磁盘上去查询
  对于 Page writes / sec ,就是在面临内存压力的时候,将内存页写入磁盘来腾出内存空间
  上面说了,直接从buffer pool中,也就是内存中读取数据和从磁盘中读取数据的时间上的差异是巨大的,对性能的影响也是很是明显的
  实际中咱们也会常常遇到这种现象,有些SQL查询语句,第一次执行比较慢,可是再次执行的时候,就相对快了不少,
  固然经过set statistics io 这个信息也能发现有第一次存在物理读的现象,这种速度上的差异,仍是比较明显的
  这两个值能够经过以下sql查询获得

select * 
from sys.dm_os_performance_counters 
where object_name like '%Buffer Manager%' and (counter_name='Page reads/sec' or counter_name='Page writes/sec' )

    若是一台服务器上常常发生大批量的物理性IO操做,你就要注意是否存在内存问题,
    由于常常性的大批量的物理IO会严重拖慢SQL的执行效率,理想状况下,这个值不该该过大,也有材料上说不能持续大于0,我我的以为有点绝对了
    其实也没有一个绝对的标准,只要这个值可以稳定在一个较低的水平,没有持续性的大批量数据的写入(磁盘)于读取(从磁盘载入内存),均可以接受
    相反,若是长期在一个高位水平,而且观察到PLE不能稳定在参考值范围内,说明内存可能存在瓶颈。

  • Lazy writes / sec

    Lazy writes 是每秒被缓冲区管理器的惰性编写器(lazy writer)写入的缓存区的数据page信息。
    Lazy writer是一个系统进程,用于批量刷新内存中的脏页到磁盘,而且将原来脏页占用的内存空间清理的一个动做。
    若是存在内存压力,Lazy writer会被触发,将脏页和长时间没有用到的计划缓存清理出内存,
    若是常常被触发,那么说明内存可能存在瓶颈
    须要注意的是,经过以下 sys.dm_os_performance_counters 查询出来的Lazy writes/sec值是一个累计值
    可是这也不妨碍咱们得出某一个时间间隔内发生的Lazy writes/sec的数据,相信聪明的你必定能够算出来 

select * 
from sys.dm_os_performance_counters 
where object_name like '%Buffer Manager%' and counter_name='Lazy writes/sec'

    对于脏页以及老化的缓存计划,有其余机制去实现写入磁盘存储并清理器占用的内存空间
    Lazy Write是在面临内存压力的状况下触发的,
    若是某一个时间间隔内,Lazy Write持续不为零,就要结合PLE以及Page reads(writes) / sec 来判断分析内存是否存在不够用的状况了。

 

 

  说完PLE和Page reads(writes) / sec 以及Lazy writes / sec以后,就能够作一个小小的总结了

  上面说了,衡量内存瓶颈的时候,一般要结合多个值来作出判断,
  若是你的PLE不在计算出来的参考值预期以内,同时又伴随着大量的Page reads(writes) / sec
  那么就几乎能够判定你的服务器存在内存瓶颈了
  由于PLE达不到预期值,也就是说可能有大量所须要的数据不存在于缓存中,
  而去读这些数据,又要进行从磁盘上的物理读取,那么就会出现Page reads(writes) / sec 较高的现象
  物理读取出来的数据要占用缓存空间(以后才能返回给查询的客户端),
  而原来缓存空间中的数据是经过Lazy writes被清理出内存,这样数据从磁盘进入缓存,而缓存中的数据又被清理出去,形成的结果就是PLE上不去
  因此结合这三个值的信息,基本上就能够判定你的内存是否存在瓶颈。

 

  固然除了上述三个计数器,还有其余更多的信息去对内存作诊断,咱们继续。

 

  • Total Server Memory/Target Server Memory

    Total Server Memory是Sql Server内存管理器“已提交”内存,说白了就是已经占用了的内存,
     而Target Server Memory则是Sql Server内存管理器可用的最大内存
    这两个值也可用经过sys.dm_os_performance_counters 查询出来

select * 
from sys.dm_os_performance_counters 
where object_name like '%Memory Manager%' and counter_name in ('Target Server Memory (KB)','Total Server Memory (KB)')

  当Total Server Memory小于Target Server Memory的时候,Sql Server还知道系统还有可用内存,在须要内存中的时候,直接跟系统申请,
  此时Total Server Memory会逐渐变大。
  可是,当Total Server Memory接近于或者等于Target Server Memory的时候,Sql Server会意识到已经用完了系统的可用内存,
  若是在须要内存的时候,系统已经没法继续分配新的内存,它就须要清理已用的内存空间,将新清理出来的空间给新的数据使用
  这个彷佛又要跟上面说的PLE以及lazy write联系上了,
  固然,系统内存空间每每是小于数据的空间的,好比有可能你的数据库文件大小是500GB,而内存以后32G或者64G,
  数据库通过一段时间的运行后,Total Server Memory老是接近于或者等于Target Server Memory的,
  那么咱们说Total Server Memory和Target Server Memory的意义何在?
  上面说了,鉴于数据文件中的数据每每都是大于可用物理内存的(固然极端例子也有,你数据库只有2GB,内存32GB)
  数据颇有可能不彻底都能缓存在内存中,可是最起码,要缓存持续到必定时间再去释放空间(给新的数据使用),而不是不停地直接去读磁盘,这就要求有一个度
  你不能说Total Server Memory老是接近于或者等于Target Server Memory,没内存用了,清理内存是正常的
  若是缓存75分钟是正常的,
  发现Total Server Memory持续性接近或者等于Target Server Memory,而PLE明显低于计算出来的参考值,低到几分钟甚至一两分钟,
  同时观察到内存跟磁盘之间频繁地、大量地物理性交换数据,这也说明,内存极有可能存在瓶颈。

     

 

 

  •  Paging File % Usage

  Paging File也即缓存文件,另一个名字叫作虚拟内存,你必定据说过,就是用拿物理磁盘空间当作内存空间使用,
  Windows系统的虚拟内存文件通常是存储在C盘的,一个叫pagefile.sys的文件,默认是隐藏的
  以下截图

  

    

  这里先说明两个问题:
  1,Sql Server会用到缓存文件吗?
  答案是:会
  2,Sql Server可否控制使用物理内存仍是page file?
  答案是:不能,一个windows上的应用,使用物理内存仍是page file,是由操做系统决定的,应用程序自己没法决定自身去使用哪一部份内存

 

  那么如何知道使用了多少缓存文件空间,经过sys.dm_os_sys_memory这个视图能够查询出来。
  固然我这个截图是在我本机,看不出来有什么特别大的使用了,一个字段是total_page_file_kb,一个是available_page_file_kb
  顾名思义,总的减去可用的,就是已用的

  

   那么,文件缓存跟内存瓶颈有什么关系呢?
  应用程序对文件缓存的使用时不受自身因素控制的,彻底是由操做系统来决定的,Sql Sever也不例外,文件缓存使用的多少固然也是由操做系统来调度
  文件缓存的使用多少能反映什么?
  若是说文件缓存使用的越多,从侧面能够反映出来服务器上当前物理内存和实际需求内存之间的差距,固然这个差距越大,说明内存缺少程度越高
  文件缓存的使用是受到Windows操做系统调度的,这一点Sql Server没法决定本身的缓存数据是存放在屋里内存中或者是page file中,
  这一点就是一个黑盒了,具体算法我无从得知
  从实际测试来看,物理内存的消耗和page file的消耗是同步的,
  举个例子,执行一个很是大的查询,经过 sys.dm_os_sys_memory能够很是清楚地观察到,
  在消耗物理内存的同时,也伴随着虚拟内存的消耗,这二者到底怎么分配,或者这之间有什么线性关系,我目前还不清楚,也但愿有高人指点
  能够很明确地说,某些生产服务器,由于缺少物理内存,32GB的物理内存的机器,
  对于文件缓存的使用达到了一个很是高的程度(30多个GB),超过了物理内存自己
  这应该就是一种非正常状态,不过这个值也没有一个权威的数据,也但愿有了解的能够留言贡献
  固然获取某些环境下有更大的文件缓存使用,我只是没见过而已。
  根据page file的使用状况,发现若是大量使用page file,甚至超过了物理内存自己,
  能够大概了解到Sql Server服务器实际所需内存与现有内存的差别程度。
  也能够在进行内存瓶颈判断的时候,做为参考指标之一。

 

 总结

     林林总总阐述了上述几个内存瓶颈压力判断指标,也仅仅是涉及到了一部分跟内存有关的计数器,固然包括但不限于上述几个值。
    若是作内存瓶颈判断,能够有更多的参考值,
    前文也说了,内存压力下,
    Sql Server是一个具有自我调节(self tuning)的应用系统,各个计数值的值是具备一系列的相关性的,每每多个性能计数器会表现出来一些一致性的特征
    好比内存不足的状况下:PLE上达不到预期值,Page reads(writes) / sec 又持续保持在一个较高的水平,同时伴随着Lazy Writer / sec 持续性的发生
    若是有更多的其它参考的判断指标,固然更具有说服力
    可是若是经过上述值,也能将内存的压力是否存在瓶颈定位个八九不离十。
    对于其余的内存相关的计数器,有时间会继续总结。
    其实说了这么些相关内容,也仅仅是对Sql Server内存一个作了一个很是粗略的分析,固然也能够对各个部分的内存分类进行进一步细化的分析和论述。

 

本文粗浅第分析了判断Sql Server内存瓶颈的一些知识点,尚有不足的地方还请指出,谢谢。但愿可以帮到各位对Sql Server感兴趣的看官,共同窗习。

相关文章
相关标签/搜索