msg*_*sme 8 sql-server sql-clr sql-server-2014 numa
我们正在使用 SQLCLR 存储过程来激活服务代理,我想监视 CLR 代码使用的内存。查看sys.dm_os_memory_clerks,我看到只有 NUMA 节点 1 具有与该MEMORYCLERK_SQLCLR类型关联的任何页面。服务器有两个 8 核 CPU,运行 SQL 2014 CU6。
这是预期的吗?或者我应该像我一样看到两个节点上使用的内存MEMORYCLERK_SQLBUFFERPOOL?
询问:
SELECT DOMC.memory_node_id
, DOMC.pages_kb
, DOMC.virtual_memory_reserved_kb
, DOMC.virtual_memory_committed_kb
FROM sys.dm_os_memory_clerks DOMC where type = 'MEMORYCLERK_SQLCLR'
Run Code Online (Sandbox Code Playgroud)
结果:
memory_node_id pages_kb virtual_memory_reserved_kb virtual_memory_committed_kb
-------------- -------------------- -------------------------- ---------------------------
0 88232 12607744 1408652
1 0 0 0
64 0 0 0
Run Code Online (Sandbox Code Playgroud)
不幸的是,没有关于 SQLCLR 内存使用细节的大量信息。然而,我确实发现以下两个资源作为起点很有帮助:
\n\n\n\n从这些内容中,并浏览各种 DMV 和 MSDN 页面来解释(好吧,这没有太多解释,但从技术上讲,它比什么都没有)这些 DMV 是如何工作的,我将下面显示的查询放在一起。从在几个不同的系统上运行这些数据来看,SQLCLR 内存分配似乎集中在一个特定的节点上memory_node_id,但在其他节点上仍然有一些分配,至少在 Proc Cache 方面是这样。因此,就目前而言,除非有人有相反的证据或信息,否则您所经历的一切都是“预期的”。
此查询报告基本信息:
\n\n\n\nSELECT domc.*\nFROM sys.dm_os_memory_clerks domc\nWHERE domc.[type] LIKE \'%CLR%\'\nAND domc.[memory_node_id] <> 64;\nRun Code Online (Sandbox Code Playgroud)\n\n您会注意到,如果不指定一个特定的[type],则还有其他一些可能会占用一些内存。我见过的总共4种类型是:
如果您想知道为什么我要过滤掉[memory_node_id]64 个,请运行以下命令:
SELECT * FROM sys.dm_os_nodes;\nRun Code Online (Sandbox Code Playgroud)\n\n您将看到node_id 64 是DAC(专用管理员连接)。
\n\n下面将为您提供两个重要字段的总计。请注意,这些字段在 SQL Server 2012 中发生了更改,因此您需要选择适合所使用的 SQL Server 版本的字段:
\n\n-- SQL Server 2012, 2014, and 2016:\nSELECT SUM(domc.pages_kb) AS [TotalPagesKb],\n SUM(domc.virtual_memory_committed_kb) AS [TotalVirtualMemoryKb]\nFROM sys.dm_os_memory_clerks domc\nWHERE domc.[type] LIKE \'%CLR%\'\nAND domc.[memory_node_id] <> 64;\n\n-- SQL Server 2005, 2008, and 2008 R2:\nSELECT SUM(domc.single_pages_kb + domc.multi_pages_kb) AS [TotalPagesKb],\n SUM(domc.virtual_memory_committed_kb) AS [TotalVirtualMemoryKb]\nFROM sys.dm_os_memory_clerks domc\nWHERE domc.[type] LIKE \'%CLR%\'\nAND domc.[memory_node_id] <> 64;\nRun Code Online (Sandbox Code Playgroud)\n\n下一个查询显示“memory_clerks”和“memory_objects”之间的关系:
\n\nSELECT domc.*, N\' \xe2\x96\x88 \' AS [ \xe2\x96\x88 ], domo.*\nFROM sys.dm_os_memory_clerks domc\nLEFT JOIN sys.dm_os_memory_objects domo\n ON domo.page_allocator_address = domc.page_allocator_address\nWHERE domc.[type] LIKE N\'%CLR%\'\nAND domc.[memory_node_id] <> 64;\nRun Code Online (Sandbox Code Playgroud)\n\n以下查询是第一个查询的更集中的版本(更类似于问题中的查询),但是 SQL Server 2012 中的字段发生了更改,因此您需要选择适合其正在使用的 SQL Server 版本的查询用于:
\n\n-- SQL Server 2012, 2014, and 2016:\nSELECT domc.memory_node_id,\n domc.[type],\n domc.pages_kb,\n domc.virtual_memory_committed_kb\nFROM sys.dm_os_memory_clerks domc\nWHERE domc.[type] LIKE \'%CLR%\'\nAND domc.[memory_node_id] <> 64;\n\n-- SQL Server 2005, 2008, and 2008 R2:\nSELECT domc.memory_node_id,\n domc.[type],\n (domc.single_pages_kb + domc.multi_pages_kb) AS [pages_kb],\n domc.virtual_memory_committed_kb\nFROM sys.dm_os_memory_clerks domc\nWHERE domc.[type] LIKE \'%CLR%\'\nAND domc.[memory_node_id] <> 64;\nRun Code Online (Sandbox Code Playgroud)\n\n更新:
\n\n我在双处理器系统上做了一些额外的测试,方法是创建 2 个数据库,并使用静态变量将 80 MB 加载到每个数据库中。我创建了两个数据库而不是一个数据库,以查看 AppDomain 是否必须保留在一个内存节点上,是否能够至少将另一个 AppDomain 放置在另一个内存节点上以便分散数据。结果:
\n\n[virtual_memory_committed_kb]领域sys.dm_os_memory_clerks增加了。而“任务管理器”中的“Commit Size”栏也反映了这一增长。