1. 程式人生 > >SQL Server內存

SQL Server內存

target 原因 環境 包含 多少 更多 導出 真的 數量

背景

最近一個客戶找到我說是所有的SQL Server 服務器的內存都被用光了,然後截圖給我看了一臺服務器的任務管理器。如圖

技術分享

這裏要說明一下任務管理器不會完整的告訴真的內存或者CPU的使用情況,也就是說這裏只能得到非精確的信息,有可能就是一個假警報。

為了讓我的客戶放心,我檢查了服務器並且查看了很多性能指標。我所看到的就是CPU和硬盤使用都是很低的只有內存是高的,這恰恰是我們期望的SQLServer 服務器的狀態。SQL Server會盡可能的使用內存,通過緩存盡可能多的磁盤來改善性能。當然如果OS需要它也會立即釋放資源回來。

SQL Server 對內存是“貪得無厭”的,它會持有所有分配給它的內存,不論是否使用。而這也是我們想要它去做的。因為它會存儲數據和執行計劃在緩存中,然後當使用完這些內存時,它不會釋放這些內存,緩存到內存中,除非兩種情況才會釋放緩存的數據內存:1) SQL Server 重啟或者內存不足 2) 操作系統需要內存
默認的內存設定就是使用所有內存(安裝時設置),當操作系統需要內存時,它也會大量釋放內存。然後等到有內存時在重新大量持有。但是這種不是最佳實踐,最好還是設定一個最大內存限制,這樣操作系統就會保證一定量的內存永遠為SQL Server 使用。

技術分享

當看到資源管理器,Available MB 的內存有兩部分組成Standby--備用和Free--可用,這Standby 的空間系統已經把它緩存了,而Free的內存意味著沒有被使用。它們都叫做可利用內存。因此針對一開始那個客戶擔憂我們大可不必太擔心。當然我們還需要健康其他的性能計數器,查明是否存在內存影響性能的隱患。需要關註的指標如下:

  • Page Life Expectancy
  • Available Bytes
  • Buffer Cache Hit Ratio
  • Target & Total Server Memory
  • Memory Grants Pending
  • Pages/sec (Hard Page Faults)
  • Batch Requests/sec & Compilations/sec

介紹下這些性能參數:

Page Life Expectancy (PLE)

這個性能計數器記錄了數據頁(非鎖定)在緩沖池中的平均時間。在生產高峰這個數值可能比較低,但是一般要保持這個數據在300s以上,數據待在緩沖中時間越長,那麽SQL的IO操作越少。

如果長期這個數值在300s以下,可以考慮增加內存,當然由於現在內存越來越大,這個值也變得不那麽重要了,但是對於中小系統依然可以作為一個標準閾值。

也可以使用下面的語句來查詢該計數器:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE 
%Buffer Manager% AND [counter_name] = Page life expectancy

Available MBytes

該計數器監測還有多少可用內存,是否操作系統存在內存壓力。一般我們調查是否這個計數器持續在500MB以下,這說明內存過低。如果持續低於500則說明你需要增加更多的內存。

這個計數器不能通過T-SQL查詢,只能通過性能監視器觀察。

Buffer Cache Hit Ratio

緩沖命中率,這個計數器記錄平均多少頻率從緩沖池中取得數據。我們在OLTP數據庫中一般這個比率是90%-95%。比率越高,這說明更少的IO操作。也相應獲得更好的性能,如果該計數器持續低於90%,則需要增加內存。

在可以使用下面的T-SQL語句查詢:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %Buffer Manager% AND [counter_name] = Buffer cache hit ratio

Target & Total Server Memory

服務器當前總內存(buffer)以及目標內存,在緩沖池初始化增加內存的時候,總內存會比目標內存稍低一點。這個比例會逐漸接近1,如果總內存沒有增長很快,就會顯著低於目標內存,這就表示如下兩點:

1) 你可以分配盡可能多的內存,SQL能緩存整個數據庫到內存中,然後如果數據庫小於機器內存,內存不會完全用光,在這種情況下,總內存將永遠小於目標內存。

2) SQL不能增加緩沖池,比如系統內存有壓力。如果這種情況你需要增加最大服務器內存,或者增加內存來改善性能。

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %Memory Manager% AND [counter_name] IN (Total Server Memory (KB),Target Server Memory (KB))

Memory Grants Pending

這個計數器測量等待內存授予的SQL的進程數量。一般推薦閾值為1或者更少。如果大於1這說明內存不足按順序等待內存釋放再操作SQL。

一般工作中出現這種等待可能是由於糟糕的查詢,缺失索引,排序或者哈希引起的。為了查明原因可以查詢DMV --sys.dm_exec_query_memory_grants 這個視圖,將會展示哪一個查詢需要內存授予執行。

如果不是以上原因引起的內存等待,則需要增加內存來解決這個問題。此時就有理由增加硬件了。查詢的T-SQL語句如下:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %Memory Manager% AND [counter_name] = Memory Grants Pending

Pages/sec (Hard Page Faults)

這裏也使用數據庫級別計數器:當需要讀取或寫入的頁不在內存中,需要到磁盤中讀取時計數。這個計數器是一個記錄讀和寫的總和並且不能直接在內存中獲取只能從因盤中讀取(導致resulting in hard page faults),這個問題是由於操作系統必須交換文件在磁盤上,當訪問內存時,內存不足則需要交換文件到磁盤上,由於磁盤讀寫速度遠低於內存,性能就會受到嚴重影響。

對於這個計數器,推薦閾值為<50,如果看到高於這個值,你可能優惠性能問題。當然,如果數據庫備份或者還原,包括導出、導入數據以及內存中映射文件等等這些也會導致性能計數器超出閾值。

Batch Request & Compilations

該計數器包含兩個檢查

  • SQL Server: SQL Statistics – Batch Request/Sec. 傳入查詢的數量(批處理數量)
  • SQL Server: SQL Statistics - Compilations/Sec. 新建立的執行計劃數量

如果Compilations/sec是25%或者相對Batch Requests/sec更高,則執行計劃將被放到緩存中,但是永遠不會重用執行計劃。寶貴的內存就被浪費了,而不是緩存數據。這是糟糕的實踐,我們要做的就是阻止這種情況,

如果Compilation/sec 很高比如100,表示有大量的即席查詢正在運行。這時可以啟用“optimize for ad hoc”把執行計劃緩存,但是只有在第二次查詢時才能被使用。

使用如下T-SQL可以得到相應的指標:

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %SQL Statistics% AND [counter_name] = Batch Requests/sec;

SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %SQL Statistics% AND [counter_name] = SQL Compilations/sec;

同樣可以獲得比率:

SELECT ROUND (100.0 * (SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %SQL Statistics% AND [counter_name] = SQL Compilations/sec) / (SELECT [cntr_value] FROM sys.dm_os_performance_counters WHERE [object_name] LIKE %SQL Statistics% AND [counter_name] = Batch Requests/sec) ,2) as [Ratio]

關於如何設定數據庫可用的內存最大值,如圖所示:

技術分享

推薦閾值:一般來說,我都是采用10%用於操作系統其它90%分配給數據庫。當然如果內存很大可以調整這個比例小於1/9,對於內存較小的通常我都預留4-6G左右給操作系統。

我們看一下實際例子:

在性能監視器中看一下這個計數器,我們可以看到這個服務器處於健康狀態下,有11GB的可用空間,沒有PageFaults(I/O只從緩存中沒有交換到磁盤),緩沖的比率為100%,PLE超過20000s,沒有內存等待,充足的總內存和較低的編譯比率(編譯數/查詢數).

技術分享

這個測量數據很容易理解,這要比任務管理器更具有作用,能依據此做出判斷是否有足夠的內存在這臺SQL Server服務器上。

總結

如果只根據任務管理器來做出判斷,我們很容易出現錯誤決定。因為不管系統多少內存,SQL Server 會盡可能的使用占用內存,這不是bug。緩存數據在內存中有很好的效果,意味著服務器是健康的,也為用戶提供了更好的執行效率。在實際數據庫環境中,一般突然遇到的性能問題多半是因為T-SQL語句引起的,就如我前面提到糟糕的查詢(缺失索引、排序、哈希等等),這個時候通過語句優化可以很好的解決突發問題,這裏就不詳解了。如果服務器普遍存在文章中出現的內存性能計數器問題,那就寫報告提交內存增加需求吧。

SQL Server內存