Buffer cache hit ratio官方是這麼解釋的:“指示在緩衝區高速緩存中找到而不需要從磁碟中讀取的頁的百分比。” Buffer cache hit ratio被很多人當做判斷記憶體的性能指標之一(我沒說僅僅只看這個計數器的值,實際上我現在都不看這個值了), 也有不少給給出了具體的參數
Buffer cache hit ratio官方是這麼解釋的:“指示在緩衝區高速緩存中找到而不需要從磁碟中讀取的頁的百分比。”
Buffer cache hit ratio被很多人當做判斷記憶體的性能指標之一(我沒說僅僅只看這個計數器的值,實際上我現在都不看這個值了),
也有不少給給出了具體的參數,諸如(OLTP)要大於95%,或者是大於98%之類的,我不知道給出具體參考值的人是不是真是地區測試過這個參數的值,是作為經驗總結還是複製粘貼?
當我去伺服器上觀察這個值的時候,似乎發現一個規律,
不管伺服器的負載如何,即便是存在較重的業務負載的時候,這個值一直是接近所謂的“理想值”(99%),難道這個值真的可以去作為衡量記憶體瓶頸的指標嗎,
實際上被這個問題困惑了好多天,
我在測試的時候,儘管不斷地去壓縮SqlServer的最大記憶體限制,
然後做壓力測試,
儘管Page life expectancy可以底到十幾二十幾毫秒,也就是記憶體已經存在很嚴重的瓶頸了,卻發現Buffer cache hit ratio這個計數器的值是99%左右,
於是開始懷疑這個計數器的演算法,如果說緩衝命中率達到99%左右,能否說明沒有記憶體瓶頸呢?
其實如果做過實際測試,應該不難發現這個問題,對於這個值,早就有人懷疑過了,明明是存在記憶體的瓶頸,緩存命中率卻顯示為99%+
只是沒發現有人提供滿意的答案,具體問題可以參考這個 http://bbs.csdn.net/topics/330018239
下麵演示一下測試步驟,測試過程可能比較粗粗略,說明其中原理即可
1,首先限制SqlServer的最大記憶體為1G,然後依次讀取容量大於1G空間的不同的表,看看性能計數器給出的結果
,
2,創建一張測試表,往裡面寫入將近1G的數據量
然後再創建跟這個表一樣大小的表,目前,這兩個表的數據都接近於1G的空間
select * into DBTEST2.dbo.TestBufferCacheHitRatio_BAK from TestBufferCacheHitRatio
3,我們知道SqlServer讀取數據的時候,粗略地講,(如果數據不在緩存中)是現將數據讀取到記憶體,然後再將數據返回給客戶端,
測試是我在本機完成的,本機資料庫伺服器沒有任何負載,測試的兩個庫也是新建的空資料庫
造完測試數據之後,
測試之前我先清除所有緩存,dbcc dropcleanbuffers,
然而,由於限制了SqlServer的最大記憶體限制而1G,忽略SqlServer非數據緩存占用的記憶體空間,可以粗略地認為,
當對第一個表讀取完後,這個表基本上占據滿了SqlServer可用記憶體空間,
如果繼續讀取另外一張類似表的數據的時候,就要從磁碟上讀取了
(實際上已經清除緩存了,主要是為了說明,第一次查詢占滿了記憶體,第二次查詢必然要從磁碟讀取到記憶體,記憶體中沒有第二次查詢的數據的緩存,即便是不清除緩存,也是一個效果),
此時觀察Buffer cache hit ratio計數器的值,理論上說,此時第二張表的數據是直接從磁碟上讀取的,也就不存在所謂的緩存,緩存命中率應該是一個非常低的值,甚至是0,如果實際來觀察所謂的“緩存命中率”的值,看看是什麼結果
截圖是第一個查詢執行完成之後,執行第二個查詢的時候,Buffer cache hit ratio性能計數器的情況,第二個查詢執行完成之後,我暫停了計數器監控,
這個結果應該是不受外界因素影響的(再次說明,我本機資料庫沒有任何負載,純粹本機做測試的一個實例,也不用反覆測試,我反覆測試了N次了,下麵會說明原因所在)
從截圖可以看到,在第一個查詢執行完成之後,第二個查詢執行的過程中,緩存命中率竟然沒有明顯的下降,最小值也是96%,平均值高達99%,第二個表的數據命名是從磁碟讀取的,當然通過IO也可以觀察出來,純粹的預讀
這不扯淡嗎,測試之前清空過緩存,並且,現有記憶體已經被第一個查詢占據滿了,明明第二張表的數據純粹第是從硬碟空間讀取的,為什麼緩存命中率Buffer cache hit ratio竟然高達99%,
難怪之前我觀察任何一臺伺服器的緩存命中率(Buffer cache hit ratio),即便是業務高峰期,都是在99%以上,原因在哪裡?
原來是Buffer cache hit ratio這個計數器在計算緩存命中率的時候,是把read ahead read,也即預讀讀取出來的數據,也算是“緩存”了,只有物理讀也即physical read算作非緩存,難怪Buffer cache hit ratio總是有這個高的值
那麼怎麼證明呢?
可以通過652這個TRACE禁用預讀(read ahead read),再同樣的測試,看看現在的緩存命中率
執行DBCC TRACEON(652, -1)之後的測試截圖
可以看到,本次同樣的測試,第一個查詢完成之後,第二查詢開始,緩存命中率有一個斷崖式的下跌,大多數時間是0 ,
平均值也不過是3%的樣子(至於為什麼存在瞬時緩存命中率的非0的高點,個人猜測是SqlServer緩存的一些進程讀取到的元數據緩存)
如果觀察IO的話,發現現在的第二個查詢沒有了預讀(read ahead read),全部是物理讀(physical read)
這也說明,對於Buffer cache hit ratio這個性能計數器的演算法,是把預讀讀取出來的數據也算作是“緩存”了,如果拿這個值去判斷記憶體瓶頸,是沒有參考意義的,當然對於記憶體瓶頸的判斷,可以用其他計數器
問題自己理解起來容易,特別是一邊測試一邊截圖,要做到恰到好處,把問題說明清楚,表達出來真不容易。以後多寫些東西鍛煉,
後記,對於自己寫的東西,經常是誠恐誠惶,生怕誤導了別人,同時發現網上有非常多的文章,提到Buffer cache hit ratio,說的似乎是言之鑿鑿,具體的參考值都給到了,不知道到底有沒有去手動驗證一下?