SqlServer 内存篇(三)—— SqlServer内存使用状况分析

142 篇文章 24 订阅

既然sqlserver内存有那么多种,每种都可能有各自上限值,DBA也必须能够看到sqlserver每种内存到底使用了多少,究竟是哪一种接近了上限、是哪部分内存不足,才能更好地解决问题。

通常可以用两种方法看到各部分内存用量——内存相关计数器和DMV视图

 

一、 内存相关计数器

与sqlserver相关的计数器通常以SQLServer:或MSSQL&<InstanceName>开头,与内存相关的主要如下:

 

1. SQLServer:Memory Manager 总体内存使用情况

  • Total Server Memory(KB):sqlserver buffer pool当前大小
  • Target Server Memory(KB):SqlServer理论上能使用的最大内存数,min(AWE,"Max Server Memory",当前服务器可用内存数)

下面是sqlserver各部分内存使用情况:

  • Optimizer Memory(KB):正在用于查询优化的状态内存数
  • SQL Cache Memory(KB):正在用于动态sqlserver高速缓存的内存数
  • Lock Memory(KB):用于锁的内存总量
  • Connection Memory(KB):正在用于维护连接的内存数
  • Granted Workspace Memory(KB):正在用于哈希、排序、索引创建等操作的内存数
  • Memory Grants Pending:等待工作空间内存授权的进程总数,大于0说明用户内存由于内存压力而被延迟。一般来说,意味着有较严重的内存瓶颈

 

2. SQLServer:Buffer Manager 数据页读写情况

buffer pool是sqlserver内存使用最多也最容易出现瓶颈的部分,因此这部分计数器非常重要。

  • Buffer Cache Hit Ratio:缓存命中率,对于OLTP,如果低于95%,可能内存不足
  • Database pages:缓冲池中数据库页数,即database cache的大小
  • Free pages:总空闲页数,正常应该在降低到一定程度后维持稳定。如果这个值过低或反复降低,可能内存不足
  • Lazy writes/sec:Lazy writer每秒写出的缓冲区数,当sqlserver感觉到内存压力时,Lazy writer会将最久未用到的内存刷到磁盘以清理内存。如果这个值很大,或者Lazy writer经常被调用,可能内存不足
  • Page Life Expectancy:页若不被引用,将在缓冲池停留的秒数。当sqlserver感觉到内存压力,Lazy writer被触发,PLE的值也会突然下降。如果PLE的值很小或者总是高高低低,不能维持在稳定水平,可能内存不足
  • Page reads/sec:每秒发出的物理数据库页读取数
  • Stolen pages:用于非database pages(包括执行计划缓存)的页数,这就是stolen memory在buffer pool中的大小
  • Target  pages:缓存池目标页数,乘以8KB就是Target Server Memory的值
  • Total pages:缓存池当前页数,乘以8KB就是Total Server Memory的值

 

二、 动态性能视图DMV

sqlserver使用Memory Clerk方式统一管理内存分配和回收,而跟踪内存使用最常用的视图也就叫做。

 

1. sqlserver各部分内存使用情况 —— sys.dm_os_memory_clerks

select      type
        , sum(virtual_memory_reserved_kb) VM_Reserved
        , sum(virtual_memory_committed_kb) VM_Commited
        , sum(awe_allocated_kb) AWE_Allocated
        , sum(shared_memory_reserved_kb) Shared_Reserved
        , sum(shared_memory_committed_kb) Shared_Commited
        --, sum(single_pages_kb)    --SQL2005、2008
        --, sum(multi_pages_kb)        --SQL2005、2008
from    sys.dm_os_memory_clerks
group by type
order by type;

字段含义如下:

  • type:Memory Clerk名称,根据名称可以大概知道用途
  • virtual_memory_reserved_kb:该Clerk reserve的虚拟内存量
  • virtual_memory_committed_kb:该Clerk commit的虚拟内存量,提交的内存应始终小于保留的内存
  • awe_allocated_kb:该Clerk 使用AWE分配的内存量,主要用于2005、2008版本
  • shared_memory_reserved_kb:该Clerk reserve以供共享内存及文件映射使用的内存量
  • shared_memory_committed_kb:该Clerk commit以供共享内存及文件映射使用的内存量,这两个字段可以追踪shared memory的大小
  • single_pages_kb:通过stolen分配的单页内存量,主要用于2005、2008版本
  • multi_pages_kb:分配的多页内存量,主要用于2005、2008版本

 

主要type如下:

  • 数据页面缓存

  • 其他对象缓存

  • 信息缓存

  • 其他sqlserver功能组件(consumer)

 

2. sqlserver缓存了哪些对象 —— sys.dm_os_buffer_descriptors

Buffer Pool的内存主要是由那个数据库占了

SELECT count(*)*8  as cached_pages_kb,CASE database_id
        WHEN 32767 THEN 'ResourceDb'
        ELSE db_name(database_id)
        END AS Database_name
FROM sys.dm_os_buffer_descriptors
GROUP BY db_name(database_id) ,database_id
ORDER BY cached_pages_kb DESC;

当前数据库的哪个表或者索引占用Pool缓冲空间最多

SELECT count(*)*8 AS cached_pages_kb,obj.name ,obj.index_id,b.type_desc,b.name
FROM sys.dm_os_buffer_descriptors AS bd
    INNER JOIN
    (
        SELECT object_name(object_id) AS name
            ,index_id ,allocation_unit_id,object_id
        FROM sys.allocation_units AS au
            INNER JOIN sys.partitions AS p
                ON au.container_id = p.hobt_id
                    AND (au.type = 1 OR au.type = 3)
        UNION ALL
        SELECT object_name(object_id) AS name  
            ,index_id, allocation_unit_id,object_id
        FROM sys.allocation_units AS au
            INNER JOIN sys.partitions AS p
                ON au.container_id = p.partition_id
                    AND au.type = 2
    ) AS obj
        ON bd.allocation_unit_id = obj.allocation_unit_id
        LEFT JOIN sys.indexes b on b.object_id = obj.object_id AND b.index_id =obj.index_id
WHERE database_id = db_id()
GROUP BY obj.name, obj.index_id ,b.name,b.type_desc
ORDER BY cached_pages_kb DESC;

Buffer Pool里面修改过的页总数大小

SELECT count(*)*8  as cached_pages_kb,
       convert(varchar(5),convert(decimal(5,2),(100-1.0*(select count(*) from sys.dm_os_buffer_descriptors b where b.database_id=a.database_id andis_modified=0)/count(*)*100.0)))+'%' modified_percentage
        ,CASE database_id
        WHEN 32767 THEN 'ResourceDb'
        ELSE db_name(database_id)
        END AS Database_name
FROM sys.dm_os_buffer_descriptors a
GROUP BY db_name(database_id) ,database_id
ORDER BY cached_pages_kb DESC;

 

 

 

3. 执行计划都缓存了什么 —— sys.dm_exec_cached_plans

  • 查询执行计划中各种对象各占多少内存
-- 查询缓存的各类执行计划,及分别占了多少内存
-- 可以对比动态查询与参数化SQL(预定义语句)的缓存量
select    cacheobjtype
        , objtype
        , sum(cast(size_in_bytes as bigint))/1024 as size_in_kb
        , count(bucketid) as cache_count
from    sys.dm_exec_cached_plans
group by cacheobjtype, objtype
order by cacheobjtype, objtype
  • 查具体存储了哪些sql

查询结果会很大,注意将结果集输出到表或文件中,直接输出到DB服务器的SMSS可能导致资源争用

-- 查询缓存中具体的执行计划,及对应的SQL
-- 将此结果按照数据表或SQL进行统计,可以作为基线,调整索引时考虑
SELECT  usecounts ,
        refcounts ,
        size_in_bytes ,
        cacheobjtype ,
        objtype ,
        TEXT
FROM    sys.dm_exec_cached_plans cp
        CROSS APPLY sys.dm_exec_sql_text(plan_handle)
ORDER BY objtype DESC ;
  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
如果 SQL Server 实例占用的内存过高,可以尝试以下方法解决: 1. 调整最大服务器内存设置。 可以通过 SQL Server Management Studio 或 Transact-SQL 命令来修改最大服务器内存设置。将最大服务器内存设置为服务器物理内存的 70% 到 80%,可以保证系统的稳定性。如果设置得太低,可能会导致性能问题。 2. 检查 SQL Server 的缓存。 可以使用以下命令来检查 SQL Server 的缓存: ``` SELECT (physical_memory_in_use_kb/1024) AS Memory_usedby_Sqlserver_MB, (locked_page_allocations_kb/1024) AS Locked_pages_used_Sqlserver_MB, (total_virtual_address_space_kb/1024) AS Total_VAS_in_MB, process_physical_memory_low, process_virtual_memory_low FROM sys.dm_os_process_memory; ``` 如果 Locked_pages_used_Sqlserver_MB 的值过高,可以考虑开启锁定页面内存选项。 3. 增加服务器内存。 如果 SQL Server 实例占用的内存过高,可以考虑增加服务器的物理内存。这可以提高系统的性能和稳定性。 4. 优化查询和索引。 如果 SQL Server 实例占用的内存过高,可能是由于查询和索引导致的。可以通过优化查询和索引来减少内存占用。可以使用 SQL Server Profiler 或 Extended Events 工具来分析查询和索引的性能。 5. 检查 SQL Server 的版本和补丁。 如果 SQL Server 实例占用的内存过高,可能是由于版本和补丁导致的。可以检查 SQL Server 的版本和补丁,确保使用的是最新版本并安装了最新的补丁。 以上是一些常见的解决方法,可以根据具体情况选择适合的方法来解决问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hehuyi_In

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值