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
--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,
(case when qs.statement_end_offset = -1
then len(convert(nvarchar(max), qt.text)) * 2
else qs.statement_end_offset
end - qs.statement_start_offset ) / 2 + 1
) as query_text
FROM sys.dm_exec_query_stats qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as qt
--where qt.text like '%select * from dbo.base_org%'
ORDER BY qs.total_physical_reads desc
--3.3.2 按照逻辑读的页面数排序,前50名。
SELECT TOP 50
qs.total_logical_reads,qs.execution_count,
qs.total_logical_reads /qs.execution_count as [Avg Logical 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
--这里必须要加1,因为有时statement_start_offset为0,那么需要取的长度要加上1,否则取出来的就会少一个字符
--如: select substring('abc',0,3) 会输出'ab',所以要写成:select substring('abc',0,3 + 1)
SUBSTRING( qt.text,
qs.statement_start_offset / 2,
case when qs.statement_end_offset = -1
then (datalength(cast(qt.text as nvarchar(max))) - qs.statement_start_offset ) / 2+ 1
else (qs.statement_end_offset - qs.statement_start_offset) / 2 + 1
end
) as query_text
FROM sys.dm_exec_query_stats qs
cross apply sys.dm_exec_sql_text(qs.sql_handle) as qt
ORDER BY qs.total_logical_reads desc
SELECT * FROM sys.dm_os_waiting_tasks ORDER BY wait_duration_ms DESC
SELECT * FROM sys.dm_os_wait_stats ORDER BY wait_time_ms DESC