请教关于Sql Server2008R2是如何对物理内存分配使用的

责任after自由 2016-03-11 11:17:03
OS:WIN SERVER 2008
DB:Sql Server2008R2
RAM:8G
Verson:SQL Server 2008 R2 Enterprise Edition (64-bit)
以上是环境详情,
最近发现内存逐渐上升,偶尔程式会报“超时”的现象
(另外:从2005/12月份建库到现在,内存从2G一直升至现在的6G,不过在建库之后有将最大内存分配了6G,即留给系统2G的内存。),眼看内存居高不下,小弟有些担心所以就着手优化所有sql存储过程及表索引并清理了索引碎片。经过整整两天的折腾也未见内存下降,所以请各位大神帮忙看看这什么原因?sql server2008是如何分配服务器的物理内存的?(情急之下翻阅了一些资料都说sql server会将所有分配的内存吃光,它内部会按需求分配来使用,但还是怀疑有些问题,毕竟内存一直这样居高不下也不太合理啊??)敬请各位大神指教!
...全文
303 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
吉普赛的歌 2016-03-11
  • 打赏
  • 举报
回复
没什么好怕的, 如果你的使用量太大, sqlserver会占用所有内存, 这是正常现象。 你唯一需要注意的是: 1. SqlServer服务器的cpu高不高?(看任务管理器) 2. 慢的SQL有哪些? 下面的sql可以帮你, 应该直接在服务器上查询:
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].Proc_DBA_GetSlowSQL') AND type in (N'P', N'PC'))
	DROP PROCEDURE [dbo].Proc_DBA_GetSlowSQL
GO
-- =============================================
-- Author:		yenange
-- Create date: 2015-12-17
-- Description:	取得最近执行缓慢的SQL语句
-- =============================================
CREATE PROCEDURE dbo.Proc_DBA_GetSlowSQL
	@topNum INT = 50						--取前多少条记录
	,@lastExecutionTime DATETIME = NULL		--最后执行时间, 默认为NULL. 为 NULL 则忽略此条件; 不为NULL 则取大于此参数之后执行的
	,@excludeNight BIT=1					--是否 排除晚上的信息? 默认=1 排除。选择是=1,后面两参数才有意义
	,@nightBegin CHAR(5)='22:00'			--"晚上"开始时间点, 默认 22:00
	,@nightEnd CHAR(5)='06:00'				--"晚上"结束时间点, 默认 06:30
	,@containSQL NVARCHAR(300)=NULL			--语句中包含的SQL. 默认为NULL. 为NULL则忽略此条件; 不为NULL则取包含此参数的记录
AS
BEGIN
	SET NOCOUNT ON
	DECLARE @nightBegin_num INT
	DECLARE @nightEnd_num INT
	SET @nightBegin_num=CAST( replace(@nightBegin,':','') AS INT)
	SET @nightEnd_num=CAST( replace(@nightEnd,':','') AS INT)
	
	SET ROWCOUNT @topNum
	SELECT 
		st.text AS SQL_Full										--父级完整语句
		,SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,
			((CASE statement_end_offset 
			WHEN -1 THEN DATALENGTH(st.text)
			ELSE qs.statement_end_offset END 
			- qs.statement_start_offset)/2) + 1) as SQL_Part	--统计对应的部分语句
		, CAST( ((qs.total_elapsed_time / 1000000.0)/qs.execution_count) AS DECIMAL(28,2) ) AS [平均消耗秒数]
		, CAST(qs.last_elapsed_time / 1000000.0 AS DECIMAL(28, 2)) AS [最后完成消耗秒数]
		, qs.last_execution_time AS [最后执行时间]
		, CAST(qs.min_elapsed_time / 1000000.0 AS DECIMAL(28, 2)) AS [最小消耗秒数]
		, CAST(qs.max_elapsed_time / 1000000.0 AS DECIMAL(28, 2)) AS [最大消耗秒数]
		, CAST(qs.total_elapsed_time / 1000000.0 AS DECIMAL(28, 2)) AS [总消耗秒数]
		, (qs.execution_count) AS [总执行次数]
		, creation_time AS [编译计划的时间]
		, CAST(qs.last_worker_time / 1000000.0 AS DECIMAL(28, 2)) AS [最后完成占用CPU秒数]
		, sql_handle,statement_start_offset,statement_end_offset
		,plan_generation_num,plan_handle,creation_time
		,last_execution_time,execution_count
		,total_worker_time,last_worker_time,min_worker_time,max_worker_time
		,total_physical_reads,last_physical_reads,min_physical_reads,max_physical_reads,total_logical_writes,last_logical_writes,min_logical_writes,max_logical_writes,total_logical_reads,last_logical_reads,min_logical_reads,max_logical_reads
		,total_clr_time,last_clr_time,min_clr_time,max_clr_time
    from sys.dm_exec_query_stats qs
        CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
	WHERE
		--1. 最后执行时间 
		(@lastExecutionTime IS NULL OR qs.last_execution_time>=@lastExecutionTime)
		--2. 包含 SQL 条件 
		AND
		(@containSQL IS NULL OR st.[text] LIKE '%'+@containSQL+'%')
		AND
		--3. 是否排除晚上
		(
			@excludeNight=0 
			OR
			(
				--2.1 开始大于结束 22:00->6:30 [ x >=6:30(end) and x<22:00(begin) ]
				@nightBegin_num>@nightEnd_num AND
				(
					CAST( replace(CONVERT(varchar(5),last_execution_time,108),':','') AS INT)>=@nightEnd_num
					AND
					CAST( replace(CONVERT(varchar(5),last_execution_time,108),':','') AS INT)<@nightBegin_num
				)
			)
			OR
			(
				--2.2 开始小于结束 1:00->6:30 [ x>=0:00 and x<1:00 or x>=6:30 and x<24:00 ]
				@nightBegin_num<@nightEnd_num AND
				(
					(
						CAST( replace(CONVERT(varchar(5),last_execution_time,108),':','') AS INT)>=0
						AND
						CAST( replace(CONVERT(varchar(5),last_execution_time,108),':','') AS INT)<@nightBegin_num
					)
					OR
					(
						CAST( replace(CONVERT(varchar(5),last_execution_time,108),':','') AS INT)>=@nightEnd_num
						AND
						CAST( replace(CONVERT(varchar(5),last_execution_time,108),':','') AS INT)<2400
					)
				)		
			)
		)
	ORDER BY qs.last_elapsed_time DESC
	
	SET NOCOUNT OFF
	SET ROWCOUNT 0
END
GO
EXEC sys.sp_addextendedproperty 
	@name=N'Version', @value=N'1.1' , 
	@level0type=N'SCHEMA',@level0name=N'dbo', 
	@level1type=N'PROCEDURE',@level1name=N'Proc_DBA_GetSlowSQL'
	
Mr_Nice 2016-03-11
  • 打赏
  • 举报
回复
SQL Server 缓冲池默认情况下,在启动 SQL Server之后,SQL Server会根据操作系统报告的物理内存数来动态增大或缩小高速缓冲存储器的容量。只要可用物理内存大小保持在4MB到10MB之间,SQL Server 缓冲池就会继续增大(保留可用物理内存在4MB到10MB之间是为了避免操作系统因为缺少内存而频繁地换页)。如果物理可用内存变得较少的时候,则SQL Server会将一些内存释放给操作系统。 就像1楼说的,sql server 总在吃内存,如果有的话,就吃掉。为了安全起见一般都会设置一个上限的内存max 设置过程大概是 服务器属性里面的内存 ,最大服务器内存。(一般会占总物理内存数的85~90%,这个需要看最大内存数是多少)
LongRui888 2016-03-11
  • 打赏
  • 举报
回复
总体上,sql server会一直占用这些内存,如果你不干预,他是不会释放的,除非是 系统内部内存紧缺,os会让sql server释放内存
责任after自由 2016-03-11
  • 打赏
  • 举报
回复
多谢各位的指导!看优化sql及索引仍是重头戏了!

22,209

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧