1. 程式人生 > >MSSQL內存架構及管理

MSSQL內存架構及管理

進行 res rtu 運行 quest 動態內存 思考 單個 RoCE

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;

MSSQL內存架構及管理