日期:2014-05-17  浏览次数:20523 次

SQL Server由内存引发的性能问题(紧急,在线等)
大家好。

我的数据库使用的是SQL Server 2008 R2,现在出现了一点问题。数据库这段时间运行一直很正常,可从今天起开始出现了严重的性能问题,读取数据非常的慢。打开活动监视器后,发现数据库I/O平均在60M每秒(在正常时平均1M每秒左右)。我对SQL Server不是很懂,别人告诉我有可能是内存问题,我在服务器属性中查到设置的最大服务器内存为我的服务器内存(接近16G),于是我把它改成了12G,结果性能立即恢复正常。可是过了一段时间以后,同样的性能问题又出现了,数据库I/O又达到了60M每秒左右,这时我再次随意调整了一下最大服务器内存(改为10G以后又改回12G),结果性能再次立即恢复正常。于是,今天我的系统像过山车一样,每隔几十分钟,当出现性能问题以后,我就调整下内存设置。一直到我发帖时 :-(

请大家帮忙分析一下,太高深的东西对我这个菜鸟来说可能不太好理解,如可能的话请指导一下如何解决或点明一个方向,非常感谢!

------解决方案--------------------
设为自动分配内存试试.

另.检查SQL2008R2 SP2补丁安装了没.
------解决方案--------------------
查PAGEFILE的使用,用性能监视器查IO内存 CPU ,另外SQL部分也查一下为什么有大的IO发生
------解决方案--------------------
突然之间,IO量暴增,肯定是由于有什么语句需要查询大量的数据,或者是执行了什么批量化的修改,删除操作。
但就像你说的,为什么调整了内存后,又正常了,这个应该还是和内存有关系。

先大概了解一下内存的使用情况,特别是里面的SinglePage和MultiPage,看看哪部分消耗比较多。

单页一般用于缓存数据,和一些简单的查询语句和执行计划,还有网络包等等。
多页一般用于非常复杂的sql语句,也就是超过了8k的语句,以及SQL Server本身的线程代码所需的内存,还有扩展存储过程xp_开头的存储过程,CLR存储过程,SP_OACreate等。

检查SQL Server的内存使用情况
select 
    type,
    
sum(virtual_memory_reserved_kb) as [VM Reserved],   --从buffer pool中保留的大小

sum(virtual_memory_committed_kb) as [VM Committed], --从buffer pool中提交的大小

--是Buffer Pool里的Stolen Memory的大小.在Buffer Pool中通过Stolen分配的,也就是直接Commit分配的内存量.
sum(single_pages_kb) as [SinlgePage Allocator],

--分配的多页内存量(KB),是使用内存节点的多页分配器分配的内存量。此内存在buffer pool外分配,是SQL Server自己的代码使用的MemToLeave大小。
sum(multi_pages_kb) as [MultiPage Allocator],

--内存Clerk使用地址窗口化扩展插件(AWE)分配的内存量。当启用AWE时,只有缓冲池Clerk(MEMORYCLERK_SQLBUFFERPOOL)使用此机制,不可为空值。
    --可以由buffer pool使用的内存量
sum(awe_allocated_kb) as [AWE Allocated],

sum(shared_memory_reserved_kb) as [SM Reserved],   --内存Clerk保留的共享内存量,保留给共享内存和文件映射使用.

sum(shared_memory_committed_kb) as [SM Committed]  --内存Clerk提交的共享内存量,和上面的字段一起可以追踪Shared Memory的大小.

from sys.dm_os_memory_clerks 
group by type
order by type


具体的,查询是由哪些语句,导致那么多的IO,特别是物理读(IO有关)和逻辑读:

--3.3 使用DMV分析SQL Server启动以来做read最多的语句

--3.3.1 按照物理读的页面数排序,前50名。
SELECT TOP 50
qs.total_physical_reads,
qs.execution_count,
    qs.total_physical_reads /qs.execution_count as [Avg Physical Read IO],
    
    qs.sql_handle,
qs.plan_handle,
qs.statement_start_offset,  --以字节为单位,但是text字段为nvarchar类型,也就是一个字符占用2个字节
qs.statement_end_offset,

qt.dbid, 
dbname=db_name(qt.dbid),
qt.objectid,               --只有procedure,trigger,view,function才会有对象id

    SUBSTRING( qt.text,
               qs.statement_start_offset / 2, 
  &