SQL Server的内存管理一共分3级,最底层是内存节点,是SQL Server内存的最低级分配对象;第二级是Memory clerks,前面提到过,它是用于访问内存节点和缓存存储的,主要用于缓存;顶级节点是内存对象,只有clerks可以访问内存节点并分配内存,所以所有需要分配内存的组件都会创建自己的memory clerks。
1.内存节点
内存节点直接映射到NUMA节点,可以通过sys.dm_os_memory_nodes来查看服务器的使用情况。如果没有做NUMA,那么memory_node_id为0。
每个内存节点有自己的memory clerks和缓存,它们平均分布在所有节点中。SQL Server的所有内存使用量就是所有节点的总和。
2.memory clerks和 Buffer Pool
memory clerks是用于内存缓存的一种机制,Buffer Pool是SQL Server内存中的最大消耗者。
(1)memory clerks
当一个对象需要分配内存时,都是通过memory clerks来实现的,SQL Server的Buffer Pool有自己的clerks(MEMORYCLERK_SQLBUFFERPOOL),而执行计划也有自己的clerks(MEMORYCLERK_SQLQUERYPLAN),这两类clerks对内存问题的侦测很有帮助,可以通过Sys.dm_os_memory_clerks这个DMV来查看相关详细信息。
SELECT [type] ,
memory_node_id ,
--page_size_bytes,--2012之前字段
--pages_kb ,--2012字段
virtual_memory_reserved_kb ,
virtual_memory_committed_kb ,
awe_allocated_kb
FROM sys.dm_os_memory_clerks
ORDER BY virtual_memory_reserved_kb DESC;
(2)Buffer Pool
在Buffer Pool中,包含和管理SQL Server的数据缓存,可以从sys.dm_os_buffer_descriptors中查询相关信息,代码清单3-1中就用这个DMV查询数据库的缓存情况。
监控SQL Server的Buffer Pool是检查内存压力时非常重要的手段。通常可以检查下面的性能计数器:
1) MSSQL$<instance >:Memory Manager\Total Server Memory (KB):Buffer Pool的大小。
2)MSSQL$<instance >:Memory Manager\Target Server Memory (KB):表示空闲的Buffer Pool大小。Total和Target的值应该尽可能相同,如果Total明显小于Target,可能意味着出现了内存压力,需要更深入地研究。
3)MSSQL$<instance >:Buffer Manager\Page Life Expectancy:代表着一个数据存在于Buffer Pool的时间。这个值越长越好,最低时间应该设置为300s。
(3)执行计划缓存(Plan Cache)
生成执行计划是花时间较多且资源开销较大的操作,所以合理地缓存执行计划是明智的选择。可以通过DMV sys.dm_exec_cached_plans来查询计划缓存的信息。比如下面的脚本可以查看当前已缓存的计划数及所占的MB数。
SELECT COUNT(*) AS 'Number of Plans' ,
SUM(CAST(size_in_bytes AS BIGINT)) / 1024 / 1024 AS 'Plan Cache Size (MB)'
FROM sys.dm_exec_cached_plans