SQL Server 的最大工作区内存会随着时间的推移而减少 - 只有重新启动实例才能增加它

SQL Server 的最大工作区内存会随着时间的推移而减少 - 只有重新启动实例才能增加它

这是一个 SQL Server 2016 CU2 实例,配置了 15 GB 作为最大 RAM 使用量。MDOP 为 4。此实例中的数据库很少被用户查询,并且这是一个只读辅助副本。

问题:每周,所有查询都会因内存耗尽而进入 RESOURCE_SEMAPHORE 状态,即使此服务器中没有其他查询同时运行。实例重新启动后,查询会重新开始工作。通过下图,您会注意到我们缺少最大工作区内存,这些查询真的非常糟糕(天文数字般的查询成本)。

重启前:可用的最大工作区内存仅有 1.8 GB,并且所有错误查询都进入 RESOURCE_SEMAPHORE 状态。

1.8GB 工作空间内存

实例重启后:有大量工作区内存(~11GB)并且不再有 RESOURCE_SEMAPHORE,即使对于糟糕的查询也是如此。

在此处输入图片描述

如您所见,这是一个令人反感的查询,要求大约 2GB 的 RAM。在此图中,SSMS 显示所需的内存实际上已授予 - 因为实例已重新启动。在重新启动之前,内存授予仍为 NULL,查询处于 RESOURCE_SEMAPHORE 等待状态。

在此处输入图片描述

现在,我们想知道的是:为什么最大工作区内存会随着时间的推移而减少,并且在没有查询运行时不会被释放?

答案1

看起来,在总共分配的 15,728,640,000 字节内存中,被盗服务器内存占用了 12,828,864,000 字节,显然没有足够的内存用于正常运行。

文档中说 SQL Server,内存管理器对象

被盗服务器内存 (KB)

指定服务器用于数据库页面之外的其他用途的内存量。

一个回答说得更多:

被盗内存是指用于排序或哈希操作(查询工作区内存)的缓冲区,或用于分配通用内存存储以存储内部数据结构(例如锁、事务上下文和连接信息)的缓冲区。惰性写入器进程不得将被盗缓冲区从缓冲池中清除。

浪费的查询显然执行了巨大的排序操作,然后 SQL Server 不会释放分配的内存。内存取自缓冲池,不能用于其他任何用途。

你的选择并不多:

  • 改进该查询,使其不对大量数据进行排序
  • 为 SQL Server 添加更多内存
  • 定期重新启动 SQL Server,尤其是在运行此查询后。

相关内容