SQL Server在占用全部内存后完全变慢

SQL Server在占用全部内存后完全变慢,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,在具有32 GB RAM的服务器上,我们有一个SQL server实例正在运行,最大内存上限为80% 内存利用率低时,一切正常。请参见下面的屏幕截图 但随着时间的推移,SQL将在3-4天内使用完整的RAM(占总RAM的80%) 在这3-4天内,我们没有对服务器进行任何更改,但它一天比一天消耗更多的内存 当它达到最大限制时,整个性能将受到影响,我们的网站将面临查询超时。执行毫秒内执行的同一查询需要许多秒 此时,我们别无选择,只能重启整个服务器,一切恢复正常。(仅重新启动服务不起作用) 这将工作一

在具有32 GB RAM的服务器上,我们有一个SQL server实例正在运行,最大内存上限为80%

内存利用率低时,一切正常。请参见下面的屏幕截图

但随着时间的推移,SQL将在3-4天内使用完整的RAM(占总RAM的80%)

在这3-4天内,我们没有对服务器进行任何更改,但它一天比一天消耗更多的内存

当它达到最大限制时,整个性能将受到影响,我们的网站将面临查询超时。执行毫秒内执行的同一查询需要许多秒

此时,我们别无选择,只能重启整个服务器,一切恢复正常。(仅重新启动服务不起作用)

这将工作一周左右,之后我们必须重新启动它

我在网上读到,SQL server不会释放内存。但他们也提到,这是SQL的工作方式,但并不影响性能。 在我的例子中,它确实如此,性能受到影响


有内存泄漏吗?或者一个存储的进程消耗大量内存却从不释放它?如果是,如何调试它?

默认情况下,如果取消上限,SQL server将消耗整个内存,并在封顶时使用所有可用内存。这是正常的。您还必须确保SQL server是框中唯一的应用程序(建议使用)和

我将使用以下方法开始故障排除

1.开始查找最消耗内存的查询,看看是否可以减少查询的内存使用量..可以通过下面的查询找到消耗内存的查询

SELECT TOP 10 SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(qt.TEXT)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2)+1),
qs.execution_count,
qs.total_logical_reads, qs.last_logical_reads,
qs.total_logical_writes, qs.last_logical_writes,
qs.total_worker_time,
qs.last_worker_time,
qs.total_elapsed_time/1000000 total_elapsed_time_in_S,
qs.last_elapsed_time/1000000 last_elapsed_time_in_S,
qs.last_execution_time,
qp.query_plan
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_logical_reads DESC -- logical reads
-- ORDER BY qs.total_logical_writes DESC -- logical writes
-- ORDER BY qs.total_worker_time DESC -- CPU time
既然您发现查询会导致高内存,那么您需要对它们进行微调,看看是否可以减少内存使用

例如:查询可能由于索引不合适而进行了多次读取,或者可能是您的IO设备由于缓冲池被多次刷新而出现问题

2.您还可以找到使用内存的顶级组件,这让您了解RAM是如何使用的

SELECT TOP(20) [type], [name], SUM(single_pages_kb) AS [SPA Mem, Kb] 
FROM sys.dm_os_memory_clerks 
GROUP BY [type], [name]  
ORDER BY SUM(single_pages_kb) DESC; 
若缓冲池一致地使用更多的内存,我不会担心这一点,但若它是cachestore_obcp,那个么您可能会有许多临时查询填满了缓存存储,这是不好的

调查的一部分会导致另一部分,因此您必须根据线索进行故障排除,因为没有一键解决方案

旁注:不推荐:
我们的一个dev实例曾经遇到过同样的问题,因此我们没有做所有的调优工作,而是使用下面的命令来立即有效地释放内存。但对于生产实例来说,这一点都不推荐,因为这会刷新缓存中存储的计划,并且您可能会面临轻微的CPU压力

DBCC FREEPROCCACHE WITH NO_INFOMSGS; 
参考文献:


您需要找出最昂贵的查询,并需要查看查询代码,很多时候查询代码没有得到有效优化。您需要进行性能调整。

我也遇到了类似的问题,但发现解决方案(有点奇怪)是将上限设置得更低。的确,SQLServer只会为自己获取尽可能多的内存,而不会释放内存。如果限制太高,那么服务器的其他功能最终会耗尽内存,整个系统必须不断交换,这会减慢一切速度,包括SQL server数据库的大小?您是否手动检查过您的函数和过程是否存在内存消耗过高的问题?@JonathanWillcock这正是为什么sql server应该安装在一台专用机器上(虚拟或物理,无所谓),除了服务器运行所需的最低限度外,没有任何其他内容。@ZoharPeled我完全同意。问题是不是每个人都有多台服务器的奢侈,对于只有一台服务器的小型组织来说,虚拟化服务器也有点过头了。你有没有可能使用CLR?+1和“你需要做的性能调整。”——这不是尤达大师很久以前说的吗?:)