優化SQL Server的記憶體占用之執行快取

2022-01-30 11:37:42 字數 4068 閱讀 9535

在論壇上常見有朋友抱怨,說sql server太吃記憶體了。這裡筆者根據經驗簡單介紹一下記憶體相關的調優知識

首先說明一下sql server記憶體占用由哪幾部分組成。sql server占用的記憶體主要由三部分組成:資料快取(data buffer)、執行快取(procedure cache)、以及sql server引擎程式。sql server引擎程式所占用快取一般相對變化不大,則我們進行記憶體調優的主要著眼點在資料快取和執行快取的控制上。本文主要介紹一下執行快取的調優。資料快取的調優將在另外的文章中介紹。 

對於減少執行快取的占用,主要可以通過使用引數化查詢減少記憶體占用。 

1、使用引數化查詢減少執行快取占用 

我們通過如下例子來說明一下使用引數化查詢對快取占用的影響。為方便試驗,我們使用了一台沒有其它負載的sql server進行如下實驗。 

下面的指令碼迴圈執行乙個簡單的查詢,共執行10000次。 

首先,我們清空一下sql server已經占用的快取: 

dbcc freeproccache 

然後,執行指令碼:

執行快取占用了90088kb,有2629個查詢計畫在快取裡,有1489頁空閒記憶體(每頁8kb)可以被資料快取和其他請求所使用。 

我們現在修改一下前面的指令碼,然後重新執行一下dbcc freeproccache。再執行一遍修改後的指令碼:

有12875頁空閒記憶體(每頁8kb)可以被資料快取所使用。 

到這裡,我們已經看到了乙個反差相當明顯的結果。在現實中,這個例子中的前者,正是經常被使用的一種執行sql指令碼的方式(例如:在程式中通過合併字串方式拼成一條sql語句,然後通過ado.net或者ado方式傳入sql server執行)。 

解釋一下原因: 

我們知道,sql語句在執行前首先將被編譯並通過查詢優化引擎進行優化,從而得到優化後的執行計畫,然後按照執行計畫被執行。對於整體相似、僅僅是引數不同的sql語句,sql server可以重用執行計畫。但對於不同的sql語句,sql server並不能重複使用以前的執行計畫,而是需要重新編譯出乙個新的執行計畫。同時,sql server在記憶體足夠使用的情況下,此時並不主動清除以前儲存的查詢計畫(注:對於長時間不再使用的查詢計畫,sql server也會定期清理)。這樣,不同的sql語句執行方式,就將會大大影響sql server中儲存的查詢計畫數目。如果限定了sql server最大可用記憶體,則過多無用的執行計畫占用,將導致sql server可用記憶體減少,從而在執行查詢時尤其是大的查詢時與磁碟發生更多的記憶體頁交換。如果沒有限定最大可用記憶體,則sql server由於可用記憶體減少,從而會占用更多記憶體。 

對此,我們一般可以通過兩種方式實現引數化查詢:一是盡可能使用儲存過程執行sql語句(這在現實中已經成為sql server dba的一條原則),二是使用sp_executesql 方式執行單個sql語句(注意不要像上面的第乙個例子那樣使用sp_executesql)。 

在現實的同乙個軟體系統中,大量的負載型別往往是類似的,所區別的也只是每次傳入的具體引數值的不同。所以使用引數化查詢是必要和可能的。另外,通過這個例子我們也看到,由於使用了引數化查詢,不僅僅是優化了sql server記憶體占用,而且由於能夠重複使用前面被編譯的執行計畫,使後面的執行不需要再次編譯,最終執行10000次查詢總共只使用了1秒鐘時間。 

2、檢查並分析sql server執行快取中的執行計畫 

通過上面的介紹,我們可以看到sql快取所占用的記憶體大小。也知道了sql server執行快取中的內容主要是各種sql語句的執行計畫。則要對快取進行優化,就可以通過具體分析快取中的執行計畫,看看哪些是有用的、哪些是無用的執行計畫來分析和定位問題。 

通過查詢dmv: sys.dm_exec_cached_plans,可以了解資料庫中的快取情況,包括被使用的次數、快取型別、占用的記憶體大小等。 

通過快取計畫的plan_handle可以查詢到該執行計畫詳細資訊,包括所對應的sql語句:

我們可以選擇針對那些執行計畫占用較大記憶體、而被重用次數較少的sql語句進行重點分析。看其呼叫方式是否合理。另外,也可以對執行計畫被重複使用次數較多的sql語句進行分析,看其執行計畫是否已經經過優化。進一步,通過對查詢計畫的分析,還可以根據需要找到系統中最占用io、cpu時間、執行次數最多的一些sql語句,然後進行相應的調優分析。篇幅所限,這裡不對此進行過多介紹。讀者可以查閱聯機叢書中的:sys.dm_exec_query_plan內容得到相關幫助。

1. 關於dbcc memory,可以檢視微軟的知識庫:

2. 關於sys.dm_exec_cached_plans和sys.dm_exec_sql_text,請參閱聯機叢書。

SQLServer佔記憶體過多的問題

經常看見有人問,mssql占用了太多的記憶體,而且還不斷的增長 或者說已經設定了使用記憶體,可是它沒有用到那麼多,這是怎麼一回事兒呢?首先,我們來看看mssql是怎樣使用記憶體的。最大的開銷一般是用於資料快取,如果記憶體足夠,它會把用過的資料和覺得你會用到的資料統統扔到記憶體中,直到記憶體不足的時候...

python threadpool的記憶體占用問題

先說結論 在使用多執行緒時,不要使用threadpool,應該使用threading,尤其是資料量大的情況。因為threadpool會導致嚴重的記憶體占用問題!對比threading和threadpool的記憶體占用 coding utf 8 import time import osimport ...

記憶體對映佔物理記憶體統計

系統 centos 語言 c 背景 搜尋引擎的索引資料很大,分布式之後,每個索引節點的索引資料還是比較大,佔了大概100g左右,全放在記憶體中是不現實的,而且因為我們的搜尋引擎不穩定,單個節點容易出現崩潰的問題,所以索引資料需要落盤到磁碟上,這樣雖然會使單個搜尋節點更加穩定,但是磁碟比記憶體的缺點就...