MSSQL内存架构及管理
1. MSSQL内存架构
相比较Oracle,MSSQL的内存区域并没那么清晰,但和Oracle类似,MSSQL内存区域大体也可以分为三个部分:buffer pool,query/workspace memory,其他cache/memory。下面,我们分别对这三个内存区域做简要介绍:
1) Bufferpool:
Buffer pool 作为MSSQL内存主要组件之一,其包括和管理MSSQL的数据缓冲。其中,buffer pool 中的每个buffer为8k大小的内存页(当然,MSSQL 64位系统上也支持large page,这里不做讨论,感兴趣的同学可以参考其他文档),与数据或索引页大小相同,这样,整个buffer pool就由这种8k大小的buffer组成。可以通过以下SQL语句来查询各数据库的buffer pool信息:
select database_id
,case database_id
when 32767 then 'resourcedb'
else db_name(database_id)
end as 'database'
,count(*)*8/1024 as 'cached size (MB)'
from sys.dm_os_buffer_descriptors
group by db_name(database_id),database_id
order by 'cached size (MB)' desc;
2) Query/workspacememory:
类似Oracle的PGA,MSSQL中,query memoy(也称为workspace memory)用于存储查询执行时哈希和排序期间的临时结果。虽然大家都知道Oracle的PGA,但MSSQL的query memory也许并没有太多文档可读,因此,也并没有太多人清楚和知道,包括MSSQL的background process,memory components等内部的一些细节和内容,都是这种现状,这也许和多方面因素相关,这里不做太多的探讨。但是,当你仔细的查看MSSQL中SQL语句的查询计划时,你会清楚的看到hash和sort等操作相关的query memory内容。
Query memory的分配出自buffer pool,因为,MSSQL内存管理器非常清楚其内存的整个分配和使用情况,这点也许和Oracle的PGA有点不同,因为,Oracle为进程模型,在其buffer pool和PGA之间转换和分配可能会比MSSQL更加复杂些,这也是MSSQL线程模型的特点和优势,关于这点,大家自己思考吧,这里不做过多的阐述。
Query memory空间可以占到buffer pool大小的25%和75%之间,但是,当buffer pool不存在内存压力时,query memory也可以进一步增长。对于所有代价低于3和query memory需求低于5M的小查询,其query memory可以为之保留整个query memory5%的空间。单个查询最多能占到整个query memory的20%以保证其他查询的正常执行,这点来说,与Oracle的PGA非常类似。可以通过以下SQL语句来获取查询语句的query memory及相关授权情况:
select session_id,sql_handle,grant_time,requested_memory_kb
,granted_memory_kb,used_memory_kb
from sys.dm_exec_query_memory_grants
order bygranted_memory_kb desc;
select sum(isnull(requested_memory_kb,0))requested_memory_kb
,sum(isnull(granted_memory_kb,0))granted_memory_kb
,sum(isnull(used_memory_kb,0))used_memory_kb
from sys.dm_exec_query_memory_grants
orderby granted_memory_kb desc;
3) 其他cache/memory:
MSSQL内存区域,除了上面讲述的buffer pool和query/workspace memory外,剩下的那就是其他cache/memory部分,该部分内存用于MSSQL中所有不能放于前述两个内存区域的内存组件。这部分虽然不像Oracle中定义的那么清晰,但基本相当于Oracle中的SGA中除去buffer pool外的其他组件,这其中,主要是shared pool。该部分区域,虽然占据的内存不多,但包含众多的内存组件,也很重要。我们可以通过以下SQL语句来查询其相关信息:
select [name],[type],pages_kb,entries_count
from sys.dm_os_memory_cache_counters
order by pages_kb desc;
此外,log cache/buffer也是大家比较关心的一个内存组件,相较于Oracle来说,MSSQL对这个内存区域的持比较保守的态度,不管是官网还是其他资料,对这块区域都未曾提及。Oracle中,我们既可以很容易的查看该区域的大小,也可以很容易的对该区域大小进行配置和更改;然而,MSSQL中该区域则是截然相反,我们对该区域既不能查看,也不能修改,真相估计也只有微软内部清楚。纵观所有可以查阅的资料,我们只是知道,MSSQL实例中的每个数据都有一个log cache/buffer,其为一段连续的内存区域,其大小并不固定,最大大小不过60k,用户不能干预该区域的管理和设置,该区域由MSSQL实例自动动态管理,仅此而已,也希望有清楚和知道这部分机制和管理配置方法的同学随时联系和讨论,先谢谢了。
2. 动态内存管理
MSSQL默认的内存管理行为动态内存管理,即在不造成系统层面内存短缺的前提下,尽可能多的获取其所需的内存,MSSQL通过windows的内存通知APIs来实现这点。这点来讲,和Oracle11g的AMM非常相似,只不过,MSSQL几乎一直是这种内存管理方式,而Oracle则是在11g之后的版本才实现,这其中涉及进程模型及内存共享实现方面的内容和细节,这里不再深入探讨。
当MSSQL启动时,将会基于各种因素(像:系统上的物理内存,服务器线程数,以及各种启动参数等)计算MSSQL进程地址空间的大小,MSSQL将会保留这个计算出大小的内存空间,但它仅仅获取当前负载需要的物理内存空间。
接下来,当更多用户连接和运行查询时,为了支撑更多的负载,MSSQL会按需获取另外的物理内存。MSSQL实例会继续获取物理内存,直到达到它的max server memory目标,或者windows通知不再有额外的自有内存可用,此时,如果实例获取的内存大于min server memory且windows通知自由内存短缺时,则MSSQL会释放内存。
Min server memory和max server memory配置选项建立了MSSQL实例所用内存的上下限。MSSQL并不会立即获取min server memory确定大小的内存,开始仅仅获取实例初始化所需大小的内存,此后,随着MSSQL实例上负载的增加,其不断获取内存以支撑这些工作负载,期间,MSSQL实例内存达到min server memory前不会释放任何已获取的内存,一旦达到min server memory值后,MSSQL实例会利用其内部内存相关算法按需获取和释放内存,和之前不同的是,MSSQL实例不再会释放内存至min server memory确定值之下,也不会获取内存至max server memory确定值之上。
实际上,MSSQL2012之前的版本中,min/max server memory并非指MSSQL实例所占用和管理的所有内存,而仅仅是指MSSQL实例中的buffer pool大小,而MSSQL实例的其他内存组件则在此之外,而MSSQL2012之后的版本中,这一切发生了变化,min/max server memory几乎包括了MSSQL实例所占用和管理的所有内存,MSSQL实例完全根据其上负载按需动态的获取和释放内存。
当运行MSSQL实例的同一计算机上其他应用启动时,它们会消耗内存且自由物理内存降到MSSQL内存目标值以下时,MSSQL实例开始调整自己的内存消耗。当其他应用停止且更多内存变得可用时,MSSQL实例开始增加它的内存分配。MSSQL实例每秒钟能释放和获取数MB的内存,以便迅速的调整内存分配。至于MSSQL实例内存使用方面的信息,可以通过以下SQL来查询:
select name,value,value_in_use,[description]
from sys.configurations
where namelike'%server memory%'
order by name;
select physical_memory_in_use_kb,locked_page_allocations_kb,
page_fault_count,memory_utilization_percentage,
available_commit_limit_kb,process_physical_memory_low,
process_virtual_memory_low
from sys.dm_os_process_memory;
----------------------------------------------------------
《高性能SQL调优精要与案例解析》
blog1:http://www.cnblogs.com/lhdz_bj
blog2:http://blog.itpub.net/8484829
blog3:http://blog.csdn.net/tuning_optmization