SQL Server内存

背景

最近一个客户找到我说是所有的SQL Server 服务器的内存都被用光了,然后截图给我看了一台服务器的任务管理器。如图

这里要说明一下任务管理器不会完整的告诉真的内存或者CPU的使用情况,也就是说这里只能得到非精确的信息,有可能就是一个假警报。

为了让我的客户放心,我检查了服务器并且查看了很多性能指标。我所看到的就是CPU和硬盘使用都是很低的只有内存是高的,这恰恰是我们期望的SQLServer 服务器的状态。SQL Server会尽可能的使用内存,通过缓存尽可能多的磁盘来改善性能。当然如果OS需要它也会立即释放资源回来。

SQL Server 对内存是“贪得无厌”的,它会持有所有分配给它的内存,不论是否使用。而这也是我们想要它去做的。因为它会存储数据和执行计划在缓存中,然后当使用完这些内存时,它不会释放这些内存,缓存到内存中,除非两种情况才会释放缓存的数据内存:1) SQL Server 重启或者内存不足 2) 操作系统需要内存 
默认的内存设定就是使用所有内存(安装时设置),当操作系统需要内存时,它也会大量释放内存。然后等到有内存时在重新大量持有。但是这种不是最佳实践,最好还是设定一个最大内存限制,这样操作系统就会保证一定量的内存永远为SQL Server 使用。

当看到资源管理器,Available MB 的内存有两部分组成Standby--备用和Free--可用,这Standby 的空间系统已经把它缓存了,而Free的内存意味着没有被使用。它们都叫做可利用内存。因此针对一开始那个客户担忧我们大可不必太担心。当然我们还需要健康其他的性能计数器,查明是否存在内存影响性能的隐患。需要关注的指标如下:

  • Page Life Expectancy
  • Available Bytes
  • Buffer Cache Hit Ratio
  • Target & Total Server Memory
  • Memory Grants Pending
  • Pages/sec (Hard Page Faults)
  • Batch Requests/sec & Compilations/sec

介绍下这些性能参数:

Page Life Expectancy (PLE)

这个性能计数器记录了数据页(非锁定)在缓冲池中的平均时间。在生产高峰这个数值可能比较低,但是一般要保持这个数据在300s以上,数据待在缓冲中时间越长,那么SQL的IO操作越少。

如果长期这个数值在300s以下,可以考虑增加内存,当然由于现在内存越来越大,这个值也变得不那么重要了,但是对于中小系统依然可以作为一个标准阈值。

也可以使用下面的语句来查询该计数器:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%Buffer Manager%‘ AND [counter_name] = ‘Page life expectancy‘

Available MBytes

该计数器监测还有多少可用内存,是否操作系统存在内存压力。一般我们调查是否这个计数器持续在500MB以下,这说明内存过低。如果持续低于500则说明你需要增加更多的内存。

这个计数器不能通过T-SQL查询,只能通过性能监视器观察。

Buffer Cache Hit Ratio

缓冲命中率,这个计数器记录平均多少频率从缓冲池中取得数据。我们在OLTP数据库中一般这个比率是90%-95%。比率越高,这说明更少的IO操作。也相应获得更好的性能,如果该计数器持续低于90%,则需要增加内存。

在可以使用下面的T-SQL语句查询:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%Buffer Manager%‘ AND [counter_name] = ‘Buffer cache hit ratio‘

Target & Total Server Memory

服务器当前总内存(buffer)以及目标内存,在缓冲池初始化增加内存的时候,总内存会比目标内存稍低一点。这个比例会逐渐接近1,如果总内存没有增长很快,就会显著低于目标内存,这就表示如下两点:

1)  你可以分配尽可能多的内存,SQL能缓存整个数据库到内存中,然后如果数据库小于机器内存,内存不会完全用光,在这种情况下,总内存将永远小于目标内存。

2)  SQL不能增加缓冲池,比如系统内存有压力。如果这种情况你需要增加最大服务器内存,或者增加内存来改善性能。

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%Memory Manager%‘ AND [counter_name] IN (‘Total Server Memory (KB)‘,‘Target Server Memory (KB)‘)

Memory Grants Pending

这个计数器测量等待内存授予的SQL的进程数量。一般推荐阈值为1或者更少。如果大于1这说明内存不足按顺序等待内存释放再操作SQL。

一般工作中出现这种等待可能是由于糟糕的查询,缺失索引,排序或者哈希引起的。为了查明原因可以查询DMV --sys.dm_exec_query_memory_grants 这个视图,将会展示哪一个查询需要内存授予执行。

如果不是以上原因引起的内存等待,则需要增加内存来解决这个问题。此时就有理由增加硬件了。查询的T-SQL语句如下:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%Memory Manager%‘ AND [counter_name] = ‘Memory Grants Pending‘

Pages/sec (Hard Page Faults)

这里也使用数据库级别计数器:当需要读取或写入的页不在内存中,需要到磁盘中读取时计数。这个计数器是一个记录读和写的总和并且不能直接在内存中获取只能从因盘中读取(导致resulting in hard page faults),这个问题是由于操作系统必须交换文件在磁盘上,当访问内存时,内存不足则需要交换文件到磁盘上,由于磁盘读写速度远低于内存,性能就会受到严重影响。

对于这个计数器,推荐阈值为<50,如果看到高于这个值,你可能优惠性能问题。当然,如果数据库备份或者还原,包括导出、导入数据以及内存中映射文件等等这些也会导致性能计数器超出阈值。

Batch Request & Compilations

该计数器包含两个检查

  • SQL Server: SQL Statistics – Batch Request/Sec.  传入查询的数量(批处理数量)
  • SQL Server: SQL Statistics - Compilations/Sec.  新建立的执行计划数量

如果Compilations/sec是25%或者相对Batch Requests/sec更高,则执行计划将被放到缓存中,但是永远不会重用执行计划。宝贵的内存就被浪费了,而不是缓存数据。这是糟糕的实践,我们要做的就是阻止这种情况,

如果Compilation/sec 很高比如100,表示有大量的即席查询正在运行。这时可以启用“optimize for ad hoc”把执行计划缓存,但是只有在第二次查询时才能被使用。

使用如下T-SQL可以得到相应的指标:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%SQL Statistics%‘ AND [counter_name] = ‘Batch Requests/sec‘;

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%SQL Statistics%‘ AND [counter_name] = ‘SQL Compilations/sec‘;

同样可以获得比率:

SELECT ROUND (100.0 * (SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%SQL Statistics%‘ AND [counter_name] = ‘SQL Compilations/sec‘) / (SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE ‘%SQL Statistics%‘ AND [counter_name] = ‘Batch Requests/sec‘) ,2) as [Ratio]

关于如何设定数据库可用的内存最大值,如图所示:

推荐阈值:一般来说,我都是采用10%用于操作系统其它90%分配给数据库。当然如果内存很大可以调整这个比例小于1/9,对于内存较小的通常我都预留4-6G左右给操作系统。

我们看一下实际例子:

在性能监视器中看一下这个计数器,我们可以看到这个服务器处于健康状态下,有11GB的可用空间,没有PageFaults(I/O只从缓存中没有交换到磁盘),缓冲的比率为100%,PLE超过20000s,没有内存等待,充足的总内存和较低的编译比率(编译数/查询数).

这个测量数据很容易理解,这要比任务管理器更具有作用,能依据此做出判断是否有足够的内存在这台SQL Server服务器上。

总结

如果只根据任务管理器来做出判断,我们很容易出现错误决定。因为不管系统多少内存,SQL Server 会尽可能的使用占用内存,这不是bug。缓存数据在内存中有很好的效果,意味着服务器是健康的,也为用户提供了更好的执行效率。在实际数据库环境中,一般突然遇到的性能问题多半是因为T-SQL语句引起的,就如我前面提到糟糕的查询(缺失索引、排序、哈希等等),这个时候通过语句优化可以很好的解决突发问题,这里就不详解了。如果服务器普遍存在文章中出现的内存性能计数器问题,那就写报告提交内存增加需求吧。

时间: 2024-08-27 08:26:57

SQL Server内存的相关文章

SQL SERVER 内存学习系列(一)

最近帮客户解决发布订阅的问题时,突然遇到这样一个问题发布订阅中报下面的错误,另外执行alter table 操作时也会报错 : 问题很奇怪发布订阅和CLR有什么关系?memtoleave内存是个啥?回忆学习体系架构的时候,确实看到过memtoleave内存,但是是什么已经完全想不起来了,所以拿起书本回味一下学习的快感... ---------------转载请注明出处------------http://www.cnblogs.com/double-K/p/5049417.html-------

SQL Server 内存中OLTP内部机制概述(一)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx ----------------------------我是分割线------------------------------- SQL S

(译)内存沉思:多个名称相关的神秘的SQL Server内存消耗者。

原文:(译)内存沉思:多个名称相关的神秘的SQL Server内存消耗者. 原文出处:https://blogs.msdn.microsoft.com/sqlmeditation/2013/01/01/memory-meditation-the-mysterious-sql-server-memory-consumer-with-many-names/ 对于多个不同名称的内存消费者 你曾经是否想知道内存授予是什么(Memory grants )?什么是查询执行的保留(预定)内存(QE Reser

学习 Sql Server 内存管理之术语理解

在学习sql server 内存管理时,看到一些term:memory node,memory clerk,memory object,非常迷惑,在此将自己的理解记录下来,以便后续学习 1,NUMA架构和memory node 内存节点基于硬件 NUMA 创建,memory node是Numa node内的内存块,属于server物理内存的一部分.Memory Node的作用是使得内存的分配由Windows移交到SQL Server OS层面执行. 查看memory node select *

SQL Server 内存中OLTP内部机制概述(二)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx 译者水平有限,如有翻译不当之处,欢迎指正. ----------------------------我是分割线---------------

SQL Server内存不足解决,以及涉及到的知识点

首选,感谢博主shield-hand的一篇文章(ms sql server缓存清除与内存释放).写的非常细致.简洁.我这里并不是自己写博客,而是用自己的思维将众多博文或官网资料做一次整合.  在讲解问题发生原因之前,我先贴出来解决方案.之后再详细剖析其深层次的原因. ms sql server缓存清除与内存释放这篇文章已经给出了非常完美的方案,我就不再赘述了.有一个问题需要注意下,就是脚本操作中最好修个成以下形式: USE [IVMS8100] GO /****** Object: Stored

SQL SERVER 内存分配及常见内存问题(2)——DMV查询

原文:SQL SERVER 内存分配及常见内存问题(2)--DMV查询 内存动态管理视图(DMV): 从sys.dm_os_memory_clerks开始. SELECT [type] , SUM(virtual_memory_reserved_kb) AS [VM Reserved] , SUM(virtual_memory_committed_kb) AS [VM Committed] , SUM(awe_allocated_kb) AS [AWE Allocated] , SUM(shar

SQL SERVER 内存分配及常见内存问题(1)——简介

原文:SQL SERVER 内存分配及常见内存问题(1)--简介 一.问题: 1.SQL Server 所占用内存数量从启动以后就不断地增加: 首先,作为成熟的产品,内存溢出的机会微乎其微.对此要了解SQL SERVER与windows是如何协调.共享内存.并且SQL SERVER的内部对内存的管理机制. 2.在Windows 2003以上版本运行的SQL Server,内存使用量突然急剧下降: 内存是Sqlserver的生命线.在errorlog中,出现一下情况:       这类问题往往不是

SQL SERVER 内存学习系列(二)-DMV查看内存信息

内存管理在SQL Server中有一个三级结构.底部是内存节点,这是最低级的分配器,用于SQL Server的内存.第二个层次是由内存Clerk组成,这是用来访问内存节点和缓存存储,缓存存储则用于缓存.最上层包含内存对象,它提供了一个比内存Clerk更小程度的粒度,内存对象允许直接.只有Clerk可以访问存储节点,来分配内存,所以每一个需要分配大量内存的组件都需要在SQL Server服务启动时创建它自己的内存Clerk. 以前版本的SQL Server需要SQL Server内存分配之外的VA

SQL Server 内存中OLTP内部机制概述(三)

----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory OLTP Internals Overview>:http://technet.microsoft.com/en-us/library/dn720242.aspx 译者水平有限,如有翻译不当之处,欢迎指正. ----------------------------我是分割线---------------