最小和最大Server內存
Min Server Memory (MB) 和 Max Server Memory (MB)控制所有SQL Server內存使用的許可大小。比起之前的版本,SQL Server 2012的Memory Manager可以更簡單地設置SQL Server內存需求的大小。SQL Server服務是以所需的最小量啟動的,並根據需要增長。一旦內存使用增長超過Min Server Memory設置,SQL Server將不會釋放任何低於該量的內存。Min Server Memory設置內存使用的下限,而Max Server Memory則設置上限。這兩個值可以使用sp_configure或通過Management Studio中的SQL Server屬性窗口的內存頁面進行設置。兩個設置中,配置緩沖池的最大值更重要,它會阻止SQL Server占用過多的內存。這在64位系統中尤其重要,因為缺少可用物理內存能夠導致Windows裁剪SQL Server的工作集。后面的“鎖定內存頁”有關於這個問題的完整描述。對於配置Max Server Memory,有一些不同的方法來計算合適的值,最直接的方法是看看SQL Server的最大使用量,及確定SQL Server之外內存需求的最大潛在用量。
查看SQL Server的最大使用量
設置SQL Server動態管理內存,然后使用性能監視器監視計數器MSSQL$<instance>:Memory Manager\Total ServerMemory (KB)。這個計數器測量SQL Server的總緩沖池使用量。如果SQL Server以外的其他需求需要比當前可用內存更多的物理內存時,Total Server Memory值會降低,然后使用任何可用內存再增加。如果您監視此計數器一段時間(包括忙時和淡時),然后你就可以將Max Server Memory設置為你觀察到的Total Server Memory (KB)的最低值,你不必擔心SQL Server在正常操作期間收縮它的使用量。
確定SQL Server之外內存需求的最大潛在用量
此選項是最流行的,因為其目的是計算出最壞的情況下,除SQL Server之外的內存需求。你應該考慮如下情況:
- 2GB用於Windows
- xGB用於SQL Server工作線程。你可以查詢sys.dm_os_sys_info來獲取最大工作線程數,每個線程會使用0.5MB(在x86系統),2MB(在x64)
- 512MB,如果你用Linked servers、擴展存儲過程dll,或通過自動化程序(Automation procedures (sp_OA calls))創建的對象
- 1~3GB,用於其他可能再系統上運行的應用程序,如備份程序或反病毒軟件
例如,在一個有8個CPU內核、64GB RAM、運行SQL Server 2012、一個第三方備份工具和病毒檢測程序的服務器上,你將考慮如下情況:
- 2GB用於Windows
- 1GB用於工作線程(576 X 2MB四舍五入)
- 512MB用於Linked Server等
- 1GB用於備份程序和病毒檢測程序
共計4.5GB,你可以將Max Server Memory配置為59.5GB
--配置服務器最大內存為59.5GB sp_configure 'max server memory (MB)',60928 go --使設置生效 Reconfigure go
檢查你的Max Server Memory是否有效
當你建立一個服務器時決定要如何配置max server memory,沒有服務器運行它期望的負載時衡量其有效性並調整它重要。要做到這一點,一個簡單的方法是使用性能監視器計數器,具體地說,MSSQL$<instance>:Buffer Manager\Page LifeExpectancy (PLE)和Memory\Available MBytes。這兩個計數器之間的平衡將告訴您max server memory設置有多大效力。PLE顯示了SQL Server希望一個頁面保持在數據緩存中多少秒,它是一個好的衡量SQL Server內存壓力的辦法。Available MBytes顯示了Windows有多少可用的物理RAM。
如果你的PLE低(<300),就檢查Available MBytes,看看有多少未使用的內存可用。如果可用的少於5MB,Windows就會開始侵略性地裁剪所有的應用程序的工作集,這被認為是一個緊急問題。如果PLE低,並且你有大量Available MBytes,你就應該增大Max Server Memory的設置,從而增加PLE;相反,如果Available MBytes低,而PLE很高,那么你就應該降低Max Server Memory設置,從而把一些RAM返還給Windows。下面是一些示例場景來說明這一點:
- 有32GB RAM的服務器Max Server Memory是30GB,PLE平均為10000,Available MBytes是90MB。解決方案:至少降低Max Server Memory 500MB。
- 有50GB RAM的服務器Max Server Memory是46GB,PLE平均是10,Available MBytes是1500MB。解決方案:增加Max Server Memory 500MB到1000MB。
- 有64GB RAM的服務器Max Server Memory是60GB,PLE平均是50,Available MBytes是20MB。解決方案:降低Max Server Memory 100MB,並購買更多RAM(盡快)。
Lock Pages in Memory
Lock Pages in Memory (LPIM)被用作應急措施(work-around),當Windows和SQL Server之間發生錯誤時,這在舊版本的SQLServer上特別不好。如果Windows沒有足夠的可用物理內存,服務來至來自驅動器或其他應用程序的資源請求,Windows將會裁剪在服務器上運行的所有應用程序的工作集(它指的是一個進程的物理內存使用情況)。這是正常的行為,應該不會有太顯著的影響。Windows Server 2003中並沒有很好地處理寫得很糟糕的驅動程序(badly written drivers),實際上可以強制所有的應用程序清空他們的工作集。這就是所謂的侵略性工作集裁剪(aggressive working set trimming),它對SQL Server的內存分配有破壞性的影響 - 因此影響性能。所以,你可以看到,當發生這種情況時,微軟增加了一個消息到SQL Server錯誤日志。下面是一個例子:
A significant part of sql server process memory hasbeen paged out.This may result in a performance degradation. Duration: 0seconds.Working set (KB): 1086400, committed (KB): 2160928, memory utilization:50%.
在Windows Server 2008中,這種行為得到顯著改變,防止了最大的問題--寫得很糟糕的驅動程序引起的應用程序工作集被清空。這不會影響SQL Server 2012,因為它只運行在Windows Server 2008+中。在SQL Server 2012中,當Windows執行工作集裁剪時,你仍然會得到記錄的消息。幾個消息能夠表明SQL Server的工作集逐漸下降(這仍然是個問題)。有兩種方式解決這個問題:
- 恰當地設置Max Server Memory,確保Windows和服務器上運行的其他進程有足夠的物理內存來執行它們的工作,而不必要求SQL Server裁剪。
- 如果你仍然看到的問題(或者,如果它的影響是非常嚴重,你不想再冒險見到它),你可以使用Locked Pages in Memory (LPIM)來配置你的SQL Server。
當LPIM啟用,SQL Server的緩沖池頁面是“鎖定”且不可分頁的(non-pageable),因此Windows在裁剪時不能占有它們。一旦頁面被鎖定,它們就不會被考慮成為用於工作集裁剪的可用內存的一部分。然而,只有SQL Server緩沖池分配才可以被鎖定,不過Windows仍然可以裁剪其他進程的工作集,這影響了SQL Server所依賴的資源。如果設置了合適的max server memory后你還繼續獲得工作集裁剪,或者SQL Server的工作集再次被裁剪的成本過於冒險,LPIM就應該被使。
如果LPIM在工作,你會在SQL Server的錯誤日志中看到如下信息:UsingLocked Pages in the Memory Manager。你可以閱讀有關Microsoft支持此功能,以及如何啟用它的內容,在http://support.microsoft.com/kb/2659143。
優化Ad-Hoc Workloads
每次生成的執行計划存放在計划緩存,以希望可以被重用,這是SQL Server管理工作負載的有效辦法之一。如果一個執行計划將不會被重用,那么它只是不必要地占用資源,使用未參數化(unparameterized)的ad-hoc T-SQL是最有可能的原因。當您在SQL Server中執行代碼,它會生成代碼的哈希值,並使用該值來決定計划重用。如果你執行一個存儲過程,散列值會根據存儲過程名稱生成,計划將在每個后續的過程調用中被重用,不管其所使用的參數值。
如果您運行存儲過程(ad-hoc T-SQL)之外的相同的代碼,哈希會對整個語句采用,包括任何文字值。當您改變文字值再次執行時,哈希是不同的,因此SQL Server不能找到匹配的哈希值,並產生一個新的執行計划,而不是重用前一個。這種情況可能會導致一個場景稱為計划緩存膨脹(bloat),由此可能會產生成千上萬的ad-hoc計划,並且緩存了為1的usecount,即使代碼基本上是相同的。理想的解決方案是使用存儲過程或函數,或參數化所有的ad-hoc T-SQL ,但是這可能是非常具有挑戰性的,而且往往無法實現,因為復雜性和公司策略。所以微軟在SQL Server 2008推出了服務器級別選項Optimize for Ad-hoc Workloads來幫助解決這個問題。當啟用了此選項,則一塊ad-hoc T-SQL在首次被執行時,SQL Server將僅僅緩存一個計划存根,而不是完整的計划。如果SQL Server隨后嘗試重用這個計划,則計划將再次產生,但這個時候是全部被緩存。這就避免了這種場景,即數以千計的單次使用的計划占用了寶貴的緩存空間。
如下圖,執行T-SQL語句得到所需結果,可以看到有超過3GB的內存用於緩存,因此很有必要查清它的使用細節。
下面將通過Cached Object Type來破壞計划緩存的大小,你可以看到有718MB的計划緩存被ad-hoc計划占用,平均使用數是20,很低。
因此,現在你想確定其中有多少是單次使用(single-use)計划,下圖表明有678MB的緩存用於那些不被重用的計划,它雖不是巨量,但它完全被浪費,因此沒有理由不清除這些計划。
Optimize for Adhoc Workloads選項可確保這種情況下不會發生,因為它僅影響ad-hoc計划,我們建議在所有SQL Server的安裝中,默認開啟它。