時間:2024-03-13 13:57作者:下載吧人氣:14
對于數據庫引擎來說,內存是一個性能提升的重要解決手段。把數據緩存起來,可以避免在查詢或更新數據時花費多余的時間,而這時間通常是從磁盤獲取數據時用來等待磁盤尋址的。把執行計劃緩存起來,可以避免重復分析執行計劃時帶來額外的CPU及各種資源的開銷。通過在內存中開辟查詢內存空間,可以迅速地完成排序、哈希等計算,達到快速返回運算結果的目的。若沒有足夠的內存空間,數據庫引擎將無法快速地響應用戶的請求。
SQL Server存儲引擎本身是一個Windows下的進程,所以SQL Server使用內存和其它Windows進程一樣,都需要向Windows申請內存(通過VirtualAlloc之類的API向Windows申請內存)。
內存芯片提供的物理存儲空間,能被CPU直接訪問,訪問速度快,易丟失。內存性能指標GB/s,ns(納秒),前者是吞吐量,后者是響應時間。磁盤性能指標MB/s,us(微秒),從兩者對比就能看出內存訪問速度是遠優于磁盤的。
物理內存容量是有限的,如果所有進程都直接使用有限的物理內存,那新的進程將無法為他們找到任何物理內存,那么物理內存將容易成為瓶頸。所以Windows會授予每個進程一個虛擬地址空間(Virtual Address Space,VAS),通過VAS建立應用程序與物理內存的橋梁。
是指一個應用程序能夠申請訪問的最大地址空間。VAS作為中間的抽象層的,不是所有的請求都直接映射到物理內存,它首先映射到VAS,然后映射到物理內存。
而兩個進程可以共用一個VAS,而VAS的大小取決于CPU架構,具體請看下面表格:
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。
VMM是負責把物理內存在系統中所有需要內存的進程之間作共享,必要時會從VAS回收物理內存,把數據存儲到頁面文件上面去,保證數據永不丟失。當進程需要內存時,VMM會從頁面文件中查找數據,并將這數據寫入一部分空閑內存當中,然后將新頁面映射到需要操作的VAS當中。
SQL Server 2012對內存管理這塊跟SQL Server 2008還是有比較大的區別的,參考一些資料,下面我們來看看兩者具體架構。
SQL Server 2008 R2:
SQL Server 2012:
名詞術語
為了更加清楚了解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 CLR的Microsoft COM對象 |
這塊內存是<=8kb的存儲,適用于sql server 2008及以前,屬于Buffer Pool緩沖池來分配。有存儲數據頁面,Consumer功能組件。
這塊內存是>8kb的存儲,適用于sql server 2008及以前,不屬于Buffer Pool緩沖池來分配, 有存儲Consumer功能組件, 第三方代碼, Threads線程。
這個適用于sql server 2012及以上,整合了single-page,multi-page統稱any size page。
它來統一響應SQL Server 內部各種組件內存申請的請求。因為這個原因,在SQL Server 2012里面,max server memory 不再像以前的版本那樣,只控制buffer pool的大小,也包括那些大于8kb 的內存請求。也就是,max server memory能夠更準確地控制SQL Server 的內存使用了。
從內存架構我們可以看到有page reservation需預先申請的內存,有momory objects從windows api申請的內存,有clr第三方申請的內存。
內存使用分類
(1)Database Cache(數據頁面緩沖區)
存放數據頁面的緩沖區。SQL Server數據庫里的數據都是以8KB為一個頁面存儲。當有用戶需要使用到這個頁面上存儲的數據時,SQL Server會把整個頁面都調入內存,供用戶使用。所以8KB是數據訪問的最小單元。當用戶修改了某個頁面上的數據時,SQL Server會在內存中將這個頁面修改,但是不會立刻將這個頁面寫回磁盤,而是等到后面的Checkpoint或Lazy Write的時候集中處理。
(2)各類Consumer
SQL Server的很多功能組件,都必須要申請內存來完成它們的任務。這些統稱為“Consumer”。常見有如下:
(3)線程內存
SQL Server會為每個進程內的每個線程分配0.5MB的內存,以存放線程的數據結構和相關信息。
(4)第三方代碼申請的內存(COM,XP…)
在SQL Server的進程里,會運行一些非SQL Server自身的代碼。例如,用戶定義的CLR或者Extended Stored Procedure代碼,Linked Server需要加載的數據連結驅動,調用SQL Mail功能需要加載的MAPI動態庫等。這些代碼也會申請內存,會算在SQL Server自己都不知道。
有些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里想辦法。
對于SQL Server自己申請的內存,有兩種內存申請單位。
小于等于8KB一個單位內存申請,SQL Server就分配一個8KB頁面。所有這些頁面都集中管理,這塊內存被稱為Buffer Pool。一次一個頁面的這種分配稱為Single Page Allocation。
對于大于8KB為單位的內存申請,SQL Server把它們集中在另外一個區域,稱為Multi-Page Allocation(舊稱MemToLeave)。而這種分配稱為Multi-Page Allocation。
類型 |
Database Cache |
Consumer |
3rh Party Code |
Threads |
Reserved/Commit |
是 |
一般不是 |
一般不是 |
不是 |
Stolen |
不是 |
是 |
是 |
是 |
Buffer Pool (Single Page) |
所有 |
絕大部分 |
沒有 |
沒有 |
MemToLeave(Multi-Page) |
沒有 |
一小部分 |
所有 |
所有 |
這里的一個例外是運行在SQL Server進程里的CLR代碼所申請的內存。這部分內存像第三方代碼一樣,也是使用MemToLeave的內存。但是,CLR可能也會用Reserve-Commit的方式申請內存。所以MemToLeave的內存也并不是都是Stolen的。
根據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)目前使用了多少內存量
網友評論