(1)SQL Server內存淺探

1.前言

對於數據庫引擎來講,內存是一個性能提高的重要解決手段。把數據緩存起來,能夠避免在查詢或更新數據時花費多餘的時間,而這時間一般是從磁盤獲取數據時用來等待磁盤尋址的。把執行計劃緩存起來,能夠避免重複分析執行計劃時帶來額外的CPU及各類資源的開銷。經過在內存中開闢查詢內存空間,能夠迅速地完成排序、哈希等計算,達到快速返回運算結果的目的。若沒有足夠的內存空間,數據庫引擎將沒法快速地響應用戶的請求。算法

2.SQL Server如何從操做系統層面分配內存

SQL Server存儲引擎自己是一個Windows下的進程,因此SQL Server使用內存和其它Windows進程同樣,都須要向Windows申請內存(經過VirtualAlloc之類的API向Windows申請內存)。sql

3.物理內存、虛擬內存、虛擬內存管理器

3.1物理內存(RAM)

內存芯片提供的物理存儲空間,能被CPU直接訪問,訪問速度快,易丟失。內存性能指標GB/s,ns(納秒),前者是吞吐量,後者是響應時間。磁盤性能指標MB/s,us(微秒),從二者對比就能看出內存訪問速度是遠優於磁盤的。數據庫

3.2虛擬內存

物理內存容量是有限的,若是全部進程都直接使用有限的物理內存,那新的進程將沒法爲他們找到任何物理內存,那麼物理內存將容易成爲瓶頸。因此Windows會授予每一個進程一個虛擬地址空間(Virtual Address Space,VAS),經過VAS創建應用程序與物理內存的橋樑。windows

3.2.1虛擬地址空間(Virtual Address Space,VAS)

是指一個應用程序可以申請訪問的最大地址空間。VAS做爲中間的抽象層的,不是全部的請求都直接映射到物理內存,它首先映射到VAS,而後映射到物理內存。
而兩個進程能夠共用一個VAS,而VAS的大小取決於CPU架構,具體請看下面表格:api

OS Type緩存

Kernel Model服務器

(內核模式)網絡

User Model數據結構

(用戶模式)架構

Total

32位系統

2GB

2GB

4GB

64位系統

8TB

8TB

16TB

VAS有兩種內存模式,Kernel Model和User Model。Kernel Model下的VAS是供Windows系統進程使用,而User Model下的VAS是供用戶進程使用。
由表格可知,32位Windows系統應用程序能夠訪問最大2GB的VAS,64Windows位系統能夠訪問最大8TB的VAS。這意味着在32位Windows系統中一個word文檔進程跟一個SQL Server進程能獲得最大2GB的VAS是同樣的。所以,從理論上講,這意味着任何應用程序進程在32位Windows系統上都將共享最大限度的2 G的VAS。

3.3虛擬內存管理器(Virtual Memory Manager,VMM)

VMM是負責把物理內存在系統中全部須要內存的進程之間做共享,必要時會從VAS回收物理內存,把數據存儲到頁面文件上面去,保證數據永不丟失。當進程須要內存時,VMM會從頁面文件中查找數據,並將這數據寫入一部分空閒內存當中,而後將新頁面映射到須要操做的VAS當中。

4.SQL Server內存架構

SQL Server 2012對內存管理這塊跟SQL Server 2008仍是有比較大的區別的,參考一些資料,下面咱們來看看二者具體架構。

SQL Server 2008 R2:                                                                                     SQL Server 2012

名詞術語

4.1緩衝池(Buffer Pool)

爲了更加清楚瞭解Buffer Pool,咱們先來了解下 SQL Server的所須要的內存有哪些,其中包括SQL Server服務(sqlserver.exe)和其它一些組件所佔用的內存,例如SQL Server代理程序(sqlagent.exe), SQL Server複製代理程序、SQL Server報表服務(ReportingServicesService.exe)、SQL Server Analysis Services(msmdsrv.exe)、SQL Server Integration Services(MsDtsSrvr.exe),和SQL Server 全文搜索(msftesql.exe)。
在一臺運行SQL Server的服務器上,運行着sqlserver服務(sqlserver.exe)和其它一些組件。在sqlserver服務(sqlserver.exe)獲取到的內存中,又分爲2大塊:一部分爲Buffer Pool,另外一部分爲非Buffer Pool,舊稱MemToReserve(默認sqlserver.exe給它預留了256MB)。下表爲這兩部份內存各自的用途:

SQL Server 進程所佔內存

Buffer Pool

EXEC sp_configure N'min server memory

EXEC sp_configure N'max server memory

Buffer Pool(即MemToReserve

(默認爲256MB), 能夠sqlserver.exe啓動時加-g參數,預留足夠內存(預留內存大小=256MB+工做線程數*512KB

Buffer Pool中主要存放以前查詢中的數據頁,和索引頁。而後根據它自已的算法,自動清理過時過訪問或效率低下的頁。

SQL Server工做線程

佔用很少

分佈式查詢引用的OLE DB訪問接口

如操做連接服務器

備份還原

維護計劃或者T-SQL備份恢復

擴展過程

sp_sys開頭的系統存儲過程,sp_OACreate 存儲過程

多頁的分配器SQL Server內存管理器

.net framework程序(它們鏈接sqlserver的網絡包大小爲8K, sqlserver默認網絡包大小爲4k

.DLL文件

 

SQL Server CLRMicrosoft COM對象

 

4.2 Single-Page

這塊內存是<=8kb的存儲,適用於sql server 2008及之前,屬於Buffer Pool緩衝池來分配。有存儲數據頁面,Consumer功能組件。

4.3 Multi-Page

這塊內存是>8kb的存儲,適用於sql server 2008及之前,不屬於Buffer Pool緩衝池來分配, 有存儲Consumer功能組件, 第三方代碼, Threads線程。

4.4 Any Size Page

這個適用於sql server 2012及以上,整合了single-page,multi-page統稱any size page。

4.5 Memory Manager

它來統一響應SQL Server 內部各類組件內存申請的請求。由於這個緣由,在SQL Server 2012裏面,max server memory 再也不像之前的版本那樣,只控制buffer pool的大小,也包括那些大於8kb 的內存請求。也就是,max server memory可以更準確地控制SQL Server 的內存使用了。

5.SQL Server 2008內存

從內存架構咱們能夠看到有page reservation需預先申請的內存,有momory objects從windows api申請的內存,有clr第三方申請的內存。

內存使用分類

5.1按用途分類

(1)Database Cache(數據頁面緩衝區)

存放數據頁面的緩衝區。SQL Server數據庫裏的數據都是以8KB爲一個頁面存儲。當有用戶須要使用到這個頁面上存儲的數據時,SQL Server會把整個頁面都調入內存,供用戶使用。因此8KB是數據訪問的最小單元。當用戶修改了某個頁面上的數據時,SQL Server會在內存中將這個頁面修改,可是不會馬上將這個頁面寫回磁盤,而是等到後面的Checkpoint或Lazy Write的時候集中處理。
(2)各種Consumer
SQL Server的不少功能組件,都必需要申請內存來完成它們的任務。這些統稱爲「Consumer」。常見有以下:
Connection:SQL Server爲每一個鏈接分配一個數據結構,存儲關於這個鏈接的信息。另外,還會分配一個輸入緩衝池,緩衝客戶端發來的指令;一個輸出緩衝池,存放SQL Server返回的結果,等待客戶端取走。
General:一組大雜燴。包括語句的編譯、範式化、每一個鎖數據結構、事務上下文、表格和索引的元數據等。
Query Plan:語句和存儲過程的執行計劃。和Database Cache相似,若是SQL Server沒有內存壓力,它就會保留每個生成的執行計劃,供之後的用戶重用,減小Comlile的消耗。因此Query Plan也會是一塊比較大的內存使用區域。
Optimizer:SQL Server在生成執行計劃的過程當中須要消耗的內存。
Utilities:像BCP、Log Manager、Parallel Queries、Backup等比較特殊的操做須要的內存。
(3)線程內存
SQL Server會爲每一個進程內的每一個線程分配0.5MB的內存,以存放線程的數據結構和相關信息。
(4)第三方代碼申請的內存(COM,XP...)
在SQL Server的進程裏,會運行一些非SQL Server自身的代碼。例如,用戶定義的CLR或者Extended Stored Procedure代碼,Linked Server須要加載的數據連結驅動,調用SQL Mail功能須要加載的MAPI動態庫等。這些代碼也會申請內存,會算在SQL Server本身都不知道。

5.2按申請方式分類

有些SQL Server內存的申請方式,是預先Reserve一塊大的內存,而後在使用的時候一小塊一小塊地Commit。而另外的內存申請則直接從空間裏Commit。在SQL Server裏,把後一種方式叫Stolen。
在SQL Server裏,對Database Cache,SQL Server會先Reserve,再Commit。其餘的全部內存使用,基本都是直接Commit,都是「Stolen」。要重申的是,Stolen內存也是正常使用的內存,不是泄漏掉的內存。
之因此要把這兩種分開,是由於SQL Server不會對Stolen的內存使用AWE功能。也就是說,AWE擴展出去的內存,只能用來存放Database Cache。其餘內存還要在原來的那2GB裏想辦法。

5.3按申請大小分類

對於SQL Server本身申請的內存,有兩種內存申請單位。
小於等於8KB一個單位內存申請,SQL Server就分配一個8KB頁面。全部這些頁面都集中管理,這塊內存被稱爲Buffer Pool。一次一個頁面的這種分配稱爲Single Page Allocation。
對於大於8KB爲單位的內存申請,SQL Server把它們集中在另一個區域,稱爲Multi-Page Allocation(舊稱MemToLeave)。而這種分配稱爲Multi-Page Allocation。

5.4各個內存分類方法之間的關係:

類型

Database Cache

Consumer

3rh Party Code

Threads

Reserved/Commit

通常不是

通常不是

不是

Stolen

不是

Buffer Pool

Single Page

全部

絕大部分

沒有

沒有

MemToLeaveMulti-Page

沒有

一小部分

全部

全部

這裏的一個例外是運行在SQL Server進程裏的CLR代碼所申請的內存。這部份內存像第三方代碼同樣,也是使用MemToLeave的內存。可是,CLR可能也會用Reserve-Commit的方式申請內存。因此MemToLeave的內存也並非都是Stolen的。

6.SQL Server 2012內存

根據SQL Server內存架構圖,咱們能夠知道,在2012版本上,Single Page Allocation跟Multi-Page Allocation合併爲Any Size Page Allocation了。而max server memory控制的不可是 Buffer Pool內存大小,而是全部大於等於小於8KB的內存請求。
如圖:

好比我設置最小服務器內存爲8G,從新啓動下SQL Server (MSSQLSERVER)服務,再使用dmv來查看當前實例的總內存空間,以及佔用內存空間:
--Target Server Memory (KB)最多能申請的內存量
--Total Server Memory (KB)目前使用了多少內存量
SELECT counter_name, ltrim(cntr_value*1.0/1024.0/1024.0)+'G'
AS memoryGB FROM sys.dm_os_performance_counters
WHERE counter_name like '%target%server%memory%'or counter_name like '%total%memory%'

從查詢結果能夠看到當咱們在SQL Server設置最小服務器內存爲8G的時候,給SQL Server分配了多少內存,它就佔用多少多少內存,從而達到性能最佳。

7.總結

這是我初次學習SQL Server性能調優方面的知識,謝謝博友花陰偷移指點。不少知識點方面可能理解有誤差,但願各個路過大神指點一二。

 

參考文獻:
Microsoft.SQL.Server企業級平臺管理實踐
SQL Server 2012 內存管理 (memory management) 改進

相關文章
相關標籤/搜索