诊断SQL Server是否有内存压力

本文介绍了SQLServer如何管理和使用内存,并提供了检查SQLServer内存压力的方法。文章详细解释了SQLServer内存占用的特点,包括缓存机制、内存计数器的含义及阈值建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道SQL Server会尽可能的获得内存来保证自己的运行,但占用内存是一个渐进的过程。SQL Server启动后,不会瞬间占用很多内存,只有当SQL Server需要更多内存时,它才试图获取更多的内存。当SQL Server不忙时,也不会释放不需要的内存(除非重启SQL Server)。因此SQL Server在启动后,会逐渐占用越来越多的内存,直到无法获取更多内存为止。因此SQL Server服务器上,在OS层面内存看起来总是快耗尽的样子。


为什么SQL Server要这样呢?因为SQL Server在内存中cache了很多数据页面,这些数据页面即使这次不用了,下次仍然有可能被使用。因此即使某次查询已经使用过了这些数据页面,SQL Server仍然会在内存中保留它们,除非有内存压力,才会吧这些过期的数据页面踢出内存。因此如果看起来SQL Server占用了10GB的内存,那么这10GB内存就会被填的满满的,即使里面可能是一些并不需要的数据。


因此如果我们要考察SQL Server是否有内存压力,需要深入SQL Server。
首先来看SQL Server实际的内存占有量'Total Server Memory (KB)':


SELECT object_name, counter_name, cntr_value AS 'Total Server Memory (KB)'
FROM sys.dm_os_performance_counters 
WHERE counter_name = 'Total Server Memory (KB)'
or counter_name = 'Target Server Memory (KB)'


Total Server Memory is what SQL currently has. Target is what it thinks it wants under the current load. So if total is lower than target, either SQL is still building up the memory allocation, or it needs more than it has (ie it's under memory pressure).因此'Target Server Memory (KB)'可能会很大,甚至超出物理内存。
但是并不准确。我就遇到过这种情况,但是内存并没有什么问题。


顺便提一句在Idera中,“SQL Used”就是'Total Server Memory (KB)', 而“SQL allocated”就是'Target Server Memory (KB)'.Idera的名字真是取的非常容易混淆啊。


下面这个链接有更多的计数器的解释:
http://msdn.microsoft.com/en-us/library/ms190924.aspx


而我们判断是否有内存压力,主要通过另外几个计数器:


Look at Page Life Expectancy, which should be well above the 300 number that most of the stuff online says.  This tells you how long pages are staying in the buffer pool, and a value of 300 equates to 5 minutes.  If you have 120GB of buffer pool and it is churning ever 5 minutes, that equates to 409.6 MB/sec sustained disk I/O for the system which is a lot of disk activity to have to sustain. 


Look at Lazy Writes/sec which tells you that number of times the buffer pool flushed dirty pages to disk outside of the CHECKPOINT process.  This should be near zero.


Look at Free Pages/sec and Free List Stalls/sec.  You don't want to see Free Pages bottom out which will result in a Free List Stall while the buffer pool has to free pages for usage.


Look at Memory Grants Pending which will tell you if you have processes waiting on workspace memory to execute.


同时还有2个OS层面的计数器:
Memory\Pages/sec
Process ( All_processes )\Working Set


我们要使用OS层面的计数器,原因是当SQL Server占用了过多的OS内存时,系统其他运行的程序就会有内存压力。此时就会发生page faulting。因此是否存在page faulting也是是否有内存压力的重要指标。系统层面的内存严重不足也会影响SQL Server的运行,因为SQL Server的很多操作如IO等,也是依赖操作系统来完成的。
Memory \ Pages/sec is the sum of Pages Input/sec and Pages Output/sec and reports the number of requested pages that were not immediately available in RAM and had to be read from the disk (resulting in hard page faults) or that had to be written to the disk to make room in RAM for other pages. Monitoring the working sets of processes enables you to correlate a particular applications memory usage with page faulting. 


具体原理见:
http://technet.microsoft.com/en-us/library/cc958290.aspx


然后是推荐的计数器阀值:

http://www.enduria.eu/key-performance-counters-and-their-thresholds-for-windows-server-recommended-by-microsoft/


最后,当memory被大量占用时,可以用一下sql查询是什么进程导致的:

SELECT
session_id,convert(varchar(max),t2.[text]) as SQlquery,t1.requested_memory_kb,
t1.granted_memory_kb,t1.required_memory_kb,t1.used_memory_kb,t1.max_used_memory_kb,t1.query_cost,t1.ideal_memory_kb

FROM sys.dm_exec_query_memory_grants t1 CROSS APPLY sys.dm_exec_sql_text(t1.sql_handle) t2
order by query_cost desc


select * from sys.dm_exec_sessions where session_id =100

SELECT DEST.TEXT  
FROM sys.[dm_exec_connections] SDEC 
 CROSS APPLY sys.[dm_exec_sql_text](SDEC.[most_recent_sql_handle]) AS DEST 
WHERE SDEC.[most_recent_session_id] = 52 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值