SQL?Server內(nèi)存機(jī)制詳解
1.前言
對(duì)于數(shù)據(jù)庫引擎來說,內(nèi)存是一個(gè)性能提升的重要解決手段。把數(shù)據(jù)緩存起來,可以避免在查詢或更新數(shù)據(jù)時(shí)花費(fèi)多余的時(shí)間,而這時(shí)間通常是從磁盤獲取數(shù)據(jù)時(shí)用來等待磁盤尋址的。把執(zhí)行計(jì)劃緩存起來,可以避免重復(fù)分析執(zhí)行計(jì)劃時(shí)帶來額外的CPU及各種資源的開銷。通過在內(nèi)存中開辟查詢內(nèi)存空間,可以迅速地完成排序、哈希等計(jì)算,達(dá)到快速返回運(yùn)算結(jié)果的目的。若沒有足夠的內(nèi)存空間,數(shù)據(jù)庫引擎將無法快速地響應(yīng)用戶的請(qǐng)求。
2.SQL Server如何從操作系統(tǒng)層面分配內(nèi)存
SQL Server存儲(chǔ)引擎本身是一個(gè)Windows下的進(jìn)程,所以SQL Server使用內(nèi)存和其它Windows進(jìn)程一樣,都需要向Windows申請(qǐng)內(nèi)存(通過VirtualAlloc之類的API向Windows申請(qǐng)內(nèi)存)。
3.物理內(nèi)存、虛擬內(nèi)存、虛擬內(nèi)存管理器
3.1物理內(nèi)存(RAM)
內(nèi)存芯片提供的物理存儲(chǔ)空間,能被CPU直接訪問,訪問速度快,易丟失。內(nèi)存性能指標(biāo)GB/s,ns(納秒),前者是吞吐量,后者是響應(yīng)時(shí)間。磁盤性能指標(biāo)MB/s,us(微秒),從兩者對(duì)比就能看出內(nèi)存訪問速度是遠(yuǎn)優(yōu)于磁盤的。
3.2虛擬內(nèi)存
物理內(nèi)存容量是有限的,如果所有進(jìn)程都直接使用有限的物理內(nèi)存,那新的進(jìn)程將無法為他們找到任何物理內(nèi)存,那么物理內(nèi)存將容易成為瓶頸。所以Windows會(huì)授予每個(gè)進(jìn)程一個(gè)虛擬地址空間(Virtual Address Space,VAS),通過VAS建立應(yīng)用程序與物理內(nèi)存的橋梁。
3.2.1虛擬地址空間(Virtual Address Space,VAS)
是指一個(gè)應(yīng)用程序能夠申請(qǐng)?jiān)L問的最大地址空間。VAS作為中間的抽象層的,不是所有的請(qǐng)求都直接映射到物理內(nèi)存,它首先映射到VAS,然后映射到物理內(nèi)存。
而兩個(gè)進(jìn)程可以共用一個(gè)VAS,而VAS的大小取決于CPU架構(gòu),具體請(qǐng)看下面表格:
OS Type | Kernel Model (內(nèi)核模式) | User Model (用戶模式) | Total |
32位系統(tǒng) | 2GB | 2GB | 4GB |
64位系統(tǒng) | 8TB | 8TB | 16TB |
VAS有兩種內(nèi)存模式,Kernel Model和User Model。Kernel Model下的VAS是供Windows系統(tǒng)進(jìn)程使用,而User Model下的VAS是供用戶進(jìn)程使用。
由表格可知,32位Windows系統(tǒng)應(yīng)用程序可以訪問最大2GB的VAS,64Windows位系統(tǒng)可以訪問最大8TB的VAS。這意味著在32位Windows系統(tǒng)中一個(gè)word文檔進(jìn)程跟一個(gè)SQL Server進(jìn)程能得到最大2GB的VAS是一樣的。因此,從理論上講,這意味著任何應(yīng)用程序進(jìn)程在32位Windows系統(tǒng)上都將共享最大限度的2 G的VAS。
3.3虛擬內(nèi)存管理器(Virtual Memory Manager,VMM)
VMM是負(fù)責(zé)把物理內(nèi)存在系統(tǒng)中所有需要內(nèi)存的進(jìn)程之間作共享,必要時(shí)會(huì)從VAS回收物理內(nèi)存,把數(shù)據(jù)存儲(chǔ)到頁面文件上面去,保證數(shù)據(jù)永不丟失。當(dāng)進(jìn)程需要內(nèi)存時(shí),VMM會(huì)從頁面文件中查找數(shù)據(jù),并將這數(shù)據(jù)寫入一部分空閑內(nèi)存當(dāng)中,然后將新頁面映射到需要操作的VAS當(dāng)中。
4.SQL Server內(nèi)存架構(gòu)
SQL Server 2012對(duì)內(nèi)存管理這塊跟SQL Server 2008還是有比較大的區(qū)別的,參考一些資料,下面我們來看看兩者具體架構(gòu)。
SQL Server 2008 R2:
SQL Server 2012:
名詞術(shù)語
4.1緩沖池(Buffer Pool)
為了更加清楚了解Buffer Pool,我們先來了解下 SQL Server的所需要的內(nèi)存有哪些,其中包括SQL Server服務(wù)(sqlserver.exe)和其它一些組件所占用的內(nèi)存,例如SQL Server代理程序(sqlagent.exe), SQL Server復(fù)制代理程序、SQL Server報(bào)表服務(wù)(ReportingServicesService.exe)、SQL Server Analysis Services(msmdsrv.exe)、SQL Server Integration Services(MsDtsSrvr.exe),和SQL Server 全文搜索(msftesql.exe)。
在一臺(tái)運(yùn)行SQL Server的服務(wù)器上,運(yùn)行著sqlserver服務(wù)(sqlserver.exe)和其它一些組件。在sqlserver服務(wù)(sqlserver.exe)獲取到的內(nèi)存中,又分為2大塊:一部分為Buffer Pool,另一部分為非Buffer Pool,舊稱MemToReserve(默認(rèn)sqlserver.exe給它預(yù)留了256MB)。下表為這兩部分內(nèi)存各自的用途:
SQL Server 進(jìn)程所占內(nèi)存 | ||
Buffer Pool EXEC sp_configure N'min server memory EXEC sp_configure N'max server memory | 非Buffer Pool(即MemToReserve) (默認(rèn)為256MB), 可以sqlserver.exe啟動(dòng)時(shí)加-g參數(shù),預(yù)留足夠內(nèi)存(預(yù)留內(nèi)存大小=256MB+工作線程數(shù)*512KB) | |
Buffer Pool中主要存放之前查詢中的數(shù)據(jù)頁,和索引頁。然后根據(jù)它自已的算法,自動(dòng)清理過期過訪問或效率低下的頁。 | SQL Server工作線程 | 占用不多 |
分布式查詢引用的OLE DB訪問接口 | 如操作鏈接服務(wù)器 | |
備份還原 | 維護(hù)計(jì)劃或者T-SQL備份恢復(fù) | |
擴(kuò)展過程 | 如sp_或sys開頭的系統(tǒng)存儲(chǔ)過程,sp_OACreate 存儲(chǔ)過程 | |
多頁的分配器SQL Server內(nèi)存管理器 | 如.net framework程序(它們連接sqlserver的網(wǎng)絡(luò)包大小為8K, sqlserver默認(rèn)網(wǎng)絡(luò)包大小為4k) | |
.DLL文件 |
| |
SQL Server CLR的Microsoft COM對(duì)象 |
4.2 Single-Page
這塊內(nèi)存是<=8kb的存儲(chǔ),適用于sql server 2008及以前,屬于Buffer Pool緩沖池來分配。有存儲(chǔ)數(shù)據(jù)頁面,Consumer功能組件。
4.3 Multi-Page
這塊內(nèi)存是>8kb的存儲(chǔ),適用于sql server 2008及以前,不屬于Buffer Pool緩沖池來分配, 有存儲(chǔ)Consumer功能組件, 第三方代碼, Threads線程。
4.4 Any Size Page
這個(gè)適用于sql server 2012及以上,整合了single-page,multi-page統(tǒng)稱any size page。
4.5 Memory Manager
它來統(tǒng)一響應(yīng)SQL Server 內(nèi)部各種組件內(nèi)存申請(qǐng)的請(qǐng)求。因?yàn)檫@個(gè)原因,在SQL Server 2012里面,max server memory 不再像以前的版本那樣,只控制buffer pool的大小,也包括那些大于8kb 的內(nèi)存請(qǐng)求。也就是,max server memory能夠更準(zhǔn)確地控制SQL Server 的內(nèi)存使用了。
5.SQL Server 2008內(nèi)存
從內(nèi)存架構(gòu)我們可以看到有page reservation需預(yù)先申請(qǐng)的內(nèi)存,有momory objects從windows api申請(qǐng)的內(nèi)存,有clr第三方申請(qǐng)的內(nèi)存。
內(nèi)存使用分類
5.1按用途分類
(1)Database Cache(數(shù)據(jù)頁面緩沖區(qū))
存放數(shù)據(jù)頁面的緩沖區(qū)。SQL Server數(shù)據(jù)庫里的數(shù)據(jù)都是以8KB為一個(gè)頁面存儲(chǔ)。當(dāng)有用戶需要使用到這個(gè)頁面上存儲(chǔ)的數(shù)據(jù)時(shí),SQL Server會(huì)把整個(gè)頁面都調(diào)入內(nèi)存,供用戶使用。所以8KB是數(shù)據(jù)訪問的最小單元。當(dāng)用戶修改了某個(gè)頁面上的數(shù)據(jù)時(shí),SQL Server會(huì)在內(nèi)存中將這個(gè)頁面修改,但是不會(huì)立刻將這個(gè)頁面寫回磁盤,而是等到后面的Checkpoint或Lazy Write的時(shí)候集中處理。
(2)各類Consumer
SQL Server的很多功能組件,都必須要申請(qǐng)內(nèi)存來完成它們的任務(wù)。這些統(tǒng)稱為“Consumer”。常見有如下:
- Connection:SQL Server為每個(gè)連接分配一個(gè)數(shù)據(jù)結(jié)構(gòu),存儲(chǔ)關(guān)于這個(gè)連接的信息。另外,還會(huì)分配一個(gè)輸入緩沖池,緩沖客戶端發(fā)來的指令;一個(gè)輸出緩沖池,存放SQL Server返回的結(jié)果,等待客戶端取走。
- General:一組大雜燴。包括語句的編譯、范式化、每個(gè)鎖數(shù)據(jù)結(jié)構(gòu)、事務(wù)上下文、表格和索引的元數(shù)據(jù)等。
- Query Plan:語句和存儲(chǔ)過程的執(zhí)行計(jì)劃。和Database Cache類似,如果SQL Server沒有內(nèi)存壓力,它就會(huì)保留每一個(gè)生成的執(zhí)行計(jì)劃,供以后的用戶重用,減少Comlile的消耗。所以Query Plan也會(huì)是一塊比較大的內(nèi)存使用區(qū)域。
- Optimizer:SQL Server在生成執(zhí)行計(jì)劃的過程中需要消耗的內(nèi)存。
- Utilities:像BCP、Log Manager、Parallel Queries、Backup等比較特殊的操作需要的內(nèi)存。
(3)線程內(nèi)存
SQL Server會(huì)為每個(gè)進(jìn)程內(nèi)的每個(gè)線程分配0.5MB的內(nèi)存,以存放線程的數(shù)據(jù)結(jié)構(gòu)和相關(guān)信息。
(4)第三方代碼申請(qǐng)的內(nèi)存(COM,XP...)
在SQL Server的進(jìn)程里,會(huì)運(yùn)行一些非SQL Server自身的代碼。例如,用戶定義的CLR或者Extended Stored Procedure代碼,Linked Server需要加載的數(shù)據(jù)連結(jié)驅(qū)動(dòng),調(diào)用SQL Mail功能需要加載的MAPI動(dòng)態(tài)庫等。這些代碼也會(huì)申請(qǐng)內(nèi)存,會(huì)算在SQL Server自己都不知道。
5.2按申請(qǐng)方式分類
有些SQL Server內(nèi)存的申請(qǐng)方式,是預(yù)先Reserve一塊大的內(nèi)存,然后在使用的時(shí)候一小塊一小塊地Commit。而另外的內(nèi)存申請(qǐng)則直接從空間里Commit。在SQL Server里,把后一種方式叫Stolen。
在SQL Server里,對(duì)Database Cache,SQL Server會(huì)先Reserve,再Commit。其他的所有內(nèi)存使用,基本都是直接Commit,都是“Stolen”。要重申的是,Stolen內(nèi)存也是正常使用的內(nèi)存,不是泄漏掉的內(nèi)存。
之所以要把這兩種分開,是因?yàn)镾QL Server不會(huì)對(duì)Stolen的內(nèi)存使用AWE功能。也就是說,AWE擴(kuò)展出去的內(nèi)存,只能用來存放Database Cache。其他內(nèi)存還要在原來的那2GB里想辦法。
5.3按申請(qǐng)大小分類
對(duì)于SQL Server自己申請(qǐng)的內(nèi)存,有兩種內(nèi)存申請(qǐng)單位。
小于等于8KB一個(gè)單位內(nèi)存申請(qǐng),SQL Server就分配一個(gè)8KB頁面。所有這些頁面都集中管理,這塊內(nèi)存被稱為Buffer Pool。一次一個(gè)頁面的這種分配稱為Single Page Allocation。
對(duì)于大于8KB為單位的內(nèi)存申請(qǐng),SQL Server把它們集中在另外一個(gè)區(qū)域,稱為Multi-Page Allocation(舊稱MemToLeave)。而這種分配稱為Multi-Page Allocation。
5.4各個(gè)內(nèi)存分類方法之間的關(guān)系:
類型 | Database Cache | Consumer | 3rh Party Code | Threads |
Reserved/Commit | 是 | 一般不是 | 一般不是 | 不是 |
Stolen | 不是 | 是 | 是 | 是 |
Buffer Pool (Single Page) | 所有 | 絕大部分 | 沒有 | 沒有 |
MemToLeave(Multi-Page) | 沒有 | 一小部分 | 所有 | 所有 |
這里的一個(gè)例外是運(yùn)行在SQL Server進(jìn)程里的CLR代碼所申請(qǐng)的內(nèi)存。這部分內(nèi)存像第三方代碼一樣,也是使用MemToLeave的內(nèi)存。但是,CLR可能也會(huì)用Reserve-Commit的方式申請(qǐng)內(nèi)存。所以MemToLeave的內(nèi)存也并不是都是Stolen的。
6.SQL Server 2012內(nèi)存
根據(jù)SQL Server內(nèi)存架構(gòu)圖,我們可以知道,在2012版本上,Single Page Allocation跟Multi-Page Allocation合并為Any Size Page Allocation了。而max server memory控制的不但是 Buffer Pool內(nèi)存大小,而是所有大于等于小于8KB的內(nèi)存請(qǐng)求。
如圖:
比如我設(shè)置最小服務(wù)器內(nèi)存為8G,重新啟動(dòng)下SQL Server (MSSQLSERVER)服務(wù),再使用dmv來查看當(dāng)前實(shí)例的總內(nèi)存空間,以及占用內(nèi)存空間:
--Target Server Memory (KB)最多能申請(qǐng)的內(nèi)存量
--Total Server Memory (KB)目前使用了多少內(nèi)存量
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%'
從查詢結(jié)果可以看到當(dāng)我們?cè)赟QL Server設(shè)置最小服務(wù)器內(nèi)存為8G的時(shí)候,給SQL Server分配了多少內(nèi)存,它就占用多少多少內(nèi)存,從而達(dá)到性能最佳。
到此這篇關(guān)于SQL Server內(nèi)存機(jī)制的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- sql server學(xué)習(xí)基礎(chǔ)之內(nèi)存初探
- SqlServer如何通過SQL語句獲取處理器(CPU)、內(nèi)存(Memory)、磁盤(Disk)以及操作系統(tǒng)相關(guān)信息
- SQL語句實(shí)現(xiàn)查詢SQL Server內(nèi)存使用狀況
- 揭秘SQL Server 2014有哪些新特性(1)-內(nèi)存數(shù)據(jù)庫
- SQL Server內(nèi)存遭遇操作系統(tǒng)進(jìn)程壓榨案例分析
- 淺談SQL Server 對(duì)于內(nèi)存的管理[圖文]
- SQL Server 數(shù)據(jù)頁緩沖區(qū)的內(nèi)存瓶頸分析
- 優(yōu)化SQL Server的內(nèi)存占用之執(zhí)行緩存
- 解決SQL Server虛擬內(nèi)存不足情況
相關(guān)文章
Activiti-Explorer使用sql server數(shù)據(jù)庫實(shí)現(xiàn)方法
本文主要介紹Activiti-Explorer使用sql server數(shù)據(jù)庫,這里整理了詳細(xì)的資料來說明Activiti-Explorer使用SQL Server的實(shí)例,有興趣的小伙伴可以參考下2016-08-08SQL server 隨機(jī)數(shù)函數(shù)
在SQL server中,有個(gè)隨機(jī)函數(shù)rand(),有不少新手可能不知道存在這個(gè)函數(shù),現(xiàn)在我就把這個(gè)函數(shù)的一些隨機(jī)數(shù)生成技巧寫出來,這是面向菜鳥的,老鳥請(qǐng)不要拍磚呀,我的頭還不夠硬2009-07-07SQLServer 數(shù)據(jù)庫變成單個(gè)用戶后無法訪問問題的解決方法
今天不知怎么點(diǎn)錯(cuò)了東西,SQLServer中的一個(gè)數(shù)據(jù)庫變成單用戶了,而且無法訪問,下面是解決方法,有需要的朋友可以參考一下2013-10-10世界杯猜想活動(dòng)的各類榜單的SQL語句小結(jié)
自己網(wǎng)站的世界杯猜想活動(dòng),整理了幾個(gè)排行榜。寫了半個(gè)小時(shí)的SQL,丟了多可惜,放在這里,反正是別人的地盤,不心疼。2010-07-07揭秘SQL Server 2014有哪些新特性(2)-固態(tài)硬盤 Buffer Pool(緩沖池) 擴(kuò)展
SQL Server 2014 中引入的緩沖池?cái)U(kuò)展提供數(shù)據(jù)庫引擎緩沖池的非易失性隨機(jī)存取內(nèi)存(即固態(tài)硬盤)擴(kuò)展的無縫集成,從而顯著提高 I/O 吞吐量。 那么今天我們來探究下,這個(gè)功能到底如何強(qiáng)悍吧2014-08-08如何使用Pycharm連接SQL?Sever(詳細(xì)教程)
這篇文章主要介紹了如何使用Pycharm連接SQL?Sever,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04select into 和 insert into select 兩種表復(fù)制語句
select into 和 insert into select 兩種表復(fù)制語句,需要的朋友可以參考下。2009-10-10SQLSERVER 語句交錯(cuò)引發(fā)的死鎖問題案例詳解
這篇文章主要介紹了SQLSERVER 語句交錯(cuò)引發(fā)的死鎖研究,要解決死鎖問題,個(gè)人感覺需要非常熟知各種隔離級(jí)別,尤其是 可提交讀 模式下的 CURD 加解鎖過程,這一篇我們就來好好聊一聊2023-02-02