SQL Server RAM 使用情况 - 如何找出它的去向?

Ian*_*oyd 0 sql-server sql-server-2012 buffer-pool

简洁版本

\n

SQL Server 使用 34 GB RAM。但当查询内存消耗报告、缓冲池大小和即席查询大小时,加起来只有 2 GB 左右。另外 32 GB RAM 有何用途?

\n

先发制人:“您应该限制 SQL Server 可以使用的 RAM 量。” 可以说它的上限x。这只是将我的问题改为“其他xGB 的 RAM 在做什么?”

\n

长版

\n

我有一个消耗 32 GB RAM 的 SQL Server 实例:

\n

在此输入图像描述

\n

这不是 32 GB虚拟内存;它实际上消耗了 32 GB物理内存(在 RAM 芯片上)——称为“工作集”

\n

而且它不像是与其他进程共享的。本质上所有这些都是 SQL Sever 私有的:

\n

在此输入图像描述

\n
    \n
  • 私有工作集:33,896,700 字节
  • \n
\n

它用那么多内存做什么?

\n

数据库缓冲池内存使用情况

\n

因此,我们按数据库查询内存使用情况 - 因为缓冲池缓存数据库中的页面:

\n
--Memory usage server wide\n;WITH src AS\n(\n    SELECT\n        database_id,\n        COUNT_BIG(*) AS db_buffer_pages\n    FROM sys.dm_os_buffer_descriptors\n    --WHERE database_id BETWEEN 5 AND 32766\n    GROUP BY database_id\n)\nSELECT\n    CASE [database_id] WHEN 32767 THEN \'Resource DB\' ELSE DB_NAME([database_id]) END AS [Database Name],\n    db_buffer_pages AS BufferPages,\n    db_buffer_pages /128.0 AS BufferMB\nFROM src\nORDER BY db_buffer_pages DESC\nOPTION(RECOMPILE, MAXDOP 1);\n
Run Code Online (Sandbox Code Playgroud)\n

32 GB 中总共4.5 MB 。

\n

TempDB 使用最多(1.4 MB),其余的从那里开始下降:

\n

在此输入图像描述

\n

32 GB 中的 5 MB - 并不占太多

\n

是的,这可能看起来很低 - 但这可能是因为我DBCC DROPCLEANBUFFERS先打电话。

\n

查询计划缓存

\n

接下来我们查询查询计划缓存。所有这些 T-SQL 语句都必须编译成一个巨大的计划,并且这些计划缓存在 RAM 中。

\n
--Server-wide memory usage of plan cache\nSELECT\n    [cacheobjtype], ObjType,\n    COUNT(1) AS Plans,\n    SUM(UseCounts) AS UseCounts,\n    SUM(CAST(size_in_bytes AS real)) / 1024.0 / 1024 AS [SizeMB]\nFROM sys.dm_exec_cached_plans\n--where [cacheobjtype] = \'Compiled Plan\' and [objtype] in (\'Adhoc\', \'Prepared\')\nGROUP BY CacheObjType, ObjType\nORDER BY SizeMB DESC\nOPTION(RECOMPILE, MAXDOP 1)\n
Run Code Online (Sandbox Code Playgroud)\n

现在我们可以看到有多少内存用于存储各种查询计划:

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n
缓存对象类型对象类型计划使用计数大小MB
编制计划过程340.21875
解析树用户选项卡110.03125
解析树看法160.0234375
\n
\n

总共250 KB -远远低于缺失的 32 GB。

\n
\n

注意:是的,这可能看起来很低 - 但这可能是因为我DBCC FREEPROCCACHE先打电话。

\n
\n

内存消耗报告

\n

上述查询显示了以下人员使用的 RAM:

\n
    \n
  • 缓冲池(将磁盘上的数据库页缓存在内存中)
  • \n
  • 查询计划缓存
  • \n
\n

这就是全部了。但 SQL Server 确实提供了内存消耗报告

\n
\n

该报告提供有关实例内组件内存消耗的详细数据

\n
\n

旁白“没有”

\n

该报告有点难以阅读:

\n

在此输入图像描述

\n

但最终的分解是:

\n
    \n
  • MEMORYCLERK_SOSNODE:131,832 KB
  • \n
  • MEMORYCLERK_SOSMEMMANAGER:71,464 KB
  • \n
  • 用户存储_数据库元数据:67,432 KB
  • \n
  • 用户存储_SCHEMAMGR:55,784 KB
  • \n
  • MEMORYCLERK_SQLSTORENG:54,280 KB
  • \n
  • MEMORYCLERK_SQLBUFFERPOOL:30,576 KB
  • \n
  • 其他:145,056 KB
  • \n
\n

总共为:556,424 KB \xe2\x86\x92 544 MB

\n

即使我们将其四舍五入到 1 GB:它仍然与 32 GB 相去甚远。

\n

那么内存去哪儿了呢?

\n

是的,我可以将 SQL Server 的 RAM 限制为 25 GB。但这只会将我的问题改为:

\n
\n

SQL Server 使用 25 GB RAM 的目的是什么?内存去哪儿了?

\n
\n

因为这对我来说听起来很像内存泄漏

\n
    \n
  • 服务器:SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64)
  • \n
\n

服务器正常运行时间

\n

可以查询服务器的正常运行时间(创建 tempdb):

\n
--Use creation date of tempdb as server start time\n
Run Code Online (Sandbox Code Playgroud)\n

SELECT SERVERPROPERTY(\'SERVERNAME\') AS ServerName, create_date AS ServerStartedDate FROM sys.databases WHERE NAME=\'tempdb\';

\n
    \n
  • 服务器开始日期2021-12-21 15:46:26.730
  • \n
\n

CLR 组件

\n
SELECT * FROM sys.assemblies\n
Run Code Online (Sandbox Code Playgroud)\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n\n\n\n
姓名主体 ID程序集 IDclr_名称权限集权限集描述可见创建日期修改日期是用户定义的
Microsoft.SqlServer.Types41microsoft.sqlserver.types,版本=11.0.0.0,文化=中性,publickeytoken=89845dcd8080cc91,处理器架构=msil3不安全访问12012-02-10 20:15:58.8432012-02-10 20:15:59.4270
\n

链接服务器

\n

select provider, provider_string from sys.servers

\n
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n
提供者提供商字符串
SQLNCLI无效的
微星DXS无效的
搜索.collat​​ordso无效的
DB2OLEDB包集合=\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\ x92;网络地址=\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92\xe2\x96\x92;网络端口=50000;连接超时=0;
\n

Han*_*dyD 5

如果您在检查内存使用情况之前运行DBCC DROPCLEANBUFFERS,它只会显示 SQL Server 使用的少量内存,但运行此命令不会将释放的内存释放回操作系统。

DBCC DROPCLEANBUFFERS将从缓冲池中删除所有干净的缓冲区,但是,sqlservr.exe 将保留之前分配的内存,并在执行后立即重新使用该内存以开始在缓冲池中分配页面DBCC DROPCLEANBUFFERS。如果您在服务器上遇到内存不足的情况,sqlservr.exe可能会开始将内存释放回操作系统,除非您启用了“锁定内存页面”

这些内存消耗查询/报告不会立即报告任何感兴趣的内容,DBCC DROPCLEANBUFFERS因为为进程分配的内存现在基本上未使用。要了解 SQL Server 如何使用其内存分配,请在运行之前运行这些查询/报告DBCC DROPCLEANBUFFERS(实际上根本不应该在生产服务器上运行)。

注意:您可以通过在 后删除最大服务器内存来强制 SQL Server 将内存释放回操作系统DBCC DROPCLEANBUFFERS。这通常不是即时的,但由于大部分未使用的页面分配给 sqlservr.exe 进程,它应该相当快地释放内存。