在我们的32 GB RAM服务器上,我们有一个运行SQL Server的实例,其最大内存为80%。
但随着时间的推移,3-4天因此SQL将使用完整的RAM(占总数的80%)。
在这3-4天内,我们不对服务器进行任何更改,但是它日复一日地占用更多内存。
当达到最大限制时,整个表现都会进行折腾,我们会在网站上面临查询超时。执行在毫秒内执行的相同查询需要几秒钟。
此时我们别无选择,只能重启整个服务器,事情恢复正常。 (仅重新启动服务不起作用)
这将工作一周左右,之后我们必须重新启动它
我在网上看过,SQL服务器没有释放内存。但他们也提到它是SQL的功能,但不会影响性能。 在我的情况下它确实存在并且性能受损。
是否有内存泄漏?或者存储过程消耗大量内存并且从不释放它?如果是这样我该怎么调试呢?
答案 0 :(得分:20)
默认情况下,如果没有上限,SQL服务器会占用整个内存,并使用上限时可用的所有内存。这是正常的。您还必须确保SQLSERVER是该框(建议使用)和also try to cap memory as per best practices上的唯一应用程序。
我会开始使用以下方法进行故障排除
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
现在您发现查询导致内存过高,您需要对它们进行微调以查看是否可以减少内存使用量。
EX:由于索引不合适,查询可能正在进行多次读取,或者由于缓冲池多次刷新而导致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。那么你可能会有许多临时查询填满缓存存储,这是不好的
调查的一部分导致另一部分,因此您将不得不根据潜在客户进行故障排除,因为没有单击解决方案
旁注:不推荐:
我们的一个开发实例曾经面对同样的问题,因此我们不再执行所有调优工作,而是运行以下命令,可以立即有效地释放内存..但这根本不适用于生产实例,因为这会冲洗计划存储在缓存中,您可能面临轻微的CPU压力
DBCC FREEPROCCACHE WITH NO_INFOMSGS;
参考文献:
答案 1 :(得分:3)
您需要找出最昂贵的查询并需要查看查询代码,很多时候查询代码没有得到有效优化。您需要进行性能调整。