1. 程式人生 > >Oracle資料庫的快取命中率

Oracle資料庫的快取命中率


資料庫快取(Block Buffer)對於Oracle資料庫的運轉和效能起著非常關鍵的作用,它佔據Oracle資料庫SGA(系統共享記憶體區)的主要部分。
Oracle資料庫通過使用LRU演算法,將最近訪問的資料塊存放到快取中,從而使對磁碟資料的訪問效率最大優化到接近於記憶體訪問的速度。
由於資料庫應用的核心操作就是資料的訪問和處理,因此如果應用系統訪問的大部分資料塊已在快取中,也就是資料在快取中命中,
那麼應用在資料訪問上的磁碟I /O等待和瓶頸將可以消除。
然而記憶體相對於現代大部分資料庫而言是非常有限的,由此資料庫快取的有效使用是非常重要的。


資料庫快取並非越大越好


Oracle文件對於資料庫快取命中率的定義為:

Hit Ratio = 1 - (physical reads / (db block gets consistent gets))。

相對而言,不命中意味著需要執行磁碟訪問。從這個計算公式可以看出,資料庫快取命中率準確地講應稱為資料塊讀命中率。也就是說,命中率僅包括快取讀操作而不包括寫操作。不幸的是,由於語義上的模糊,使我們在許多時候將快取命中率理解為資料庫快取讀寫操作的命中率。因此,我們經常會這樣認為,如果不命中率減少一半,相應地系統在讀寫資料塊方面的I/O操作也會減少一半。

在3、4年前,高階Unix伺服器的記憶體配置一般不會超過4GB,資料庫規模一般也在幾個G到幾十個G之間,SGA的配置一般在1G左右。而到了2002年,工作組級的伺服器如Sun的V880標準配置就有4GB記憶體,今天,資料庫的規模已經上升到100GB到1TB之間,配置4GB或更大的SGA區已成為許多管理員的選擇。在這種趨勢下,配置多大的SGA比較合適成了一個需要考慮的問題。由於SGA區越大意味著有更多的塊可以保留在記憶體中,進而意味著資料庫可以獲得更高的快取命中率和更好的應用程式響應時間,那麼是不是快取越大越好呢?因為伺服器記憶體畢竟是昂貴的,獲得理想的投資收益比是這個問題考慮的基礎。

首先,與任何型別的快取一樣,快取的合適尺寸取決於最頻繁訪問的資料集合(工作集)的大小,這個數值就是資料庫快取配置的一個臨界值。當資料庫快取的大小超過這個臨界值後,資料庫快取命中率隨快取加大而上升的比率將變得非常緩慢,應用程式響應速度的改進也變得不明顯;在此之後,要增加幾個百分點的命中率,也許需要新增更大量的記憶體。工作集的大小則由應用程式的資料訪問模式決定,它與資料庫的規模並沒有直接的關聯。一個非常龐大的資料庫,其中一般存在著較大比例的靜態資料,同時也許還有較大量的只寫資料,它們在平時被訪問的頻率非常低;而真正被應用系統頻繁訪問的資料也許只有非常小的一部分,只要能確保這部分資料被快取在記憶體中,資料庫快取的作用也就獲得了充分發揮,對於訪問頻度非常低的資料快取是沒有太大意義的。因此合適的資料庫快取大小取決於應用系統資料訪問的分佈程度,對於完全隨機分佈的訪問模式,除非將整個資料庫快取到記憶體中,否則擴大快取配置是不會有太大效果的。我們的目標則是在保證理想的應用系統響應速度前提下,儘量節省不必要的硬體投資。

當然,一個生產系統投入使用後,其硬體配置是不可能輕易改變的。隨著系統執行時間的推移,新的應用程式可能會不斷開發出來並投入執行,它們將與Oracle資料庫共同分享系統記憶體。當系統記憶體壓力達到一定程度而出現頻繁頁面交換時,我們可能需要考慮通過減小Oracle資料庫SGA區來緩解記憶體緊張。當進一步減小SGA區而造成資料庫系能下降時,我們所要考慮的將是對系統記憶體進行擴容。

另一方面,Oracle對Buffer Cache通過使用一系列的連結串列來管理,資料塊通過Hash演算法定位到相應的連結串列中;
資料庫快取越大,需要管理的資料庫塊也越多,相應地管理龐大數量記憶體塊的開銷將增大。
如對於16GB的Buffer Cache和8k的Block Size,將有2097152個數據塊需要管理。
也許當SGA達到一定規模時,這種開銷所產生的負面影響將顯現出來,在配置大型SGA前,有必要進行相應的效能測試。


快取命中率並非越高越好


 
也許任何一個DBA都知道,在實際生產系統中,一個非常低的命中率的確意味著系統配置或應用存在嚴重問題;但不幸的是,大多數人卻不知道一個非常高(大於99%)的快取命中率也往往同樣意味著應用中存在嚴重低效率的SQL語句,因為只有這些極差的SQL語句的存在,才有可能製造出如此之高的命中。

 
高水平的快取命中率並不能代表系統擁有良好的效能,命中率與系統性能之間並沒有直接的關係。許多非常差的系統擁有非常高的命中率,而命中率低的系統可以是執行得非常快的系統。而非常高的快取命中率(99%以上)幾乎意味著效率極差的SQL語句的存在。如果我們將提高命中率作為解決效能問題的首選途徑,那麼我們就會為系統增加記憶體並擴大資料庫快取配置,而這種努力和投入的結果往往會令人失望;因為實際中的絕大多數效能問題是低劣的SQL所造成,而依賴擴大快取配置來改善這些語句的執行效率顯然是不會有太大幫助的。實際上,命中率最大用處在新系統的測試調整階段,它可以幫助我們評估系統所需的快取配置。當系統投入實際執行後,對於具體效能問題的處理則需要對系統進行會話事件級的分析,如果仍然通過命中率的角度來分析的話,將極有可能陷入盲目和不確定的掙扎中。不幸的是,大多數人在進行Oracle資料庫效能優化時,只有當系統的快取命中率在95%以上而且問題仍然無法解決時,才會開始考慮應用程式一級的診斷和調整。

說到這裡,也許讀者會產生困惑,如果不使用命中率來作為解決效能問題的方法,那又該使用何種方法?根據我的經歷,通過分析存在問題的程序對應的等待事件和SQL語句是最為有效和直接的途徑;它可以通過設定相應程序的trace(10046)事件,然後分析trace檔案來實現。實時的系統監控則可以通過查詢v$session_wait、v$session、v$sqltext檢視來獲取對等的資料。


資料庫快取與應用的訪問模式相關
 


總的來說,什麼樣的資料庫快取命中率和多大的快取才是合適的取決於應用系統的資料訪問模式。對於資料訪問不均衡的系統(現實中的大部分情況),可能較小的快取就可以獲得理想的命中率;而對於資料訪問非常均衡的系統,非常大的快取配置也許都難以有70%以上的命中率。對於後一種情況,除了在資料庫級和應用程式上進行必要的優化,如使用多Buffer Cache功能確保參照表訪問的完全命中外,必需規劃、構建一個高效的I/O子系統,以為Oracle的資料讀寫提供最短的平均服務時間。我們所要需要做的是確保資料庫快取能夠保留系統執行時重複訪問的資料構成的工作集,另外在根據實際資料讀寫需求為其它部分資料塊分配相應的快取。如果結合Oracle8的多快取功能,將以全表掃描方式訪問的大表放入RECYCLE POOL,系統性能將會有很好的改善。

配置過大的資料庫快取常常會掩蓋應用程式中存在的嚴重效能問題,這將延後問題的發現,增加應用調優的複雜度。實際上在絕大多數情況下,我們可以通過應用程式的SQL語句和業務邏輯演算法的優化,極大提高應用程式的響應速度,同時大幅度降低系統負荷,而不需要被追加投資、系統擴容等複雜而漫長的解決方案所困擾。