【每日一摩斯】-Shared Pool優化和Library Cache Latch衝突優化 (1523934.1)-系列1

bisal發表於2013-09-07

什麼是Shared Pool?

       Oracle的例項主要包括共享記憶體(主要是SGA,還有PGA)和Background Processes,其中SGA中又包括了Shared Pool、Buffer Cache、Redo Log Buffer以及其它一些記憶體區。

       Oracle在SGA的一個特定區域中保留SQL語句、Package是、物件資訊以及其它一些內容,這就是Shared Pool。這個共享記憶體區域是由一個複雜的cache和heap manager 構成的。它需要解決三個基本問題:

1. 每次分配的記憶體大小是不一致的,從幾個位元組到上千個位元組;

2. 因為shared pool的目的是為了最大化共享資訊,所以不是每次一個使用者用完之後就可以釋放這段記憶體(在傳統的heap manager方式會遇到這個問題)。記憶體中的資訊可能對於其他session來說是有用的——Oracle並不能事先知道這些內容是否會被再次用到;

3. Shared pool中的內容不能被寫入到硬碟區域中,這一點和傳統cache是不一樣的。只有“可重建”的資訊可以被覆蓋,因為他們可以在下次需要時重建。

       基於這些背景,我們就可以理解shared pool的管理是一件非常複雜的事情。

       MOS介紹這部分知識時提到了若干術語:

(1)、Literal SQL(翻譯過來又叫字面SQL)

一個Literal SQL語句是指在predicate中使用具體值,而不是使用繫結變數,即不同的執行語句使用的具體值可能是不一樣的。

例1:應用程式使用了:

SELECT * FROM emp WHERE ename='CLARK';

而不是:

SELECT * FROM emp WHERE ename=:bind1;

例2: 以下語句不用繫結變數但是也不會被認為是literal SQL,因為這個語句可以被多次執行共享。

SELECT sysdate FROM dual;

例 3: 如果整個應用都是用相同的值'2.0'來檢查'version'的話,那麼這個語句可以被認為是可以共享的。

SELECT version  FROM app_version WHERE version>2.0;

(2)、Hard Parse(硬解析)

簡單講,一個新的SQL被執行,但又不在Shared Pool中,那麼它將被完整地解析一次(這裡的過程其實很多,主要包括語法語義檢查、執行計劃的解讀與選擇),這其中牽扯到訪問dictionary cache、Shared pool latch的獲取、執行計劃的計算等等,其中執行計劃的計算是最耗CPU資源的。

(3)、Soft Parse(軟解析)

與硬解析相對的,如果一個session請求的一個已經在Shared pool的SQL語句,無需進行上述執行計劃計算等這些步驟,就被稱為‘Soft Parse',對於應用來說,它只需請求解析這個語句。(實際上還有所謂的軟軟解析)。

(4)、完全相同的語句?

如果兩個SQL語句的含義相同但是沒有使用相同的字元,那麼Oracle認為它們是不同的語句。比如SCOTT在一個Session中提交的這兩個語句:

SELECT ENAME from EMP;

SELECT ename from emp;

儘管它們實際上是相同的,但是因為大寫字母‘E’和小寫字母'e'的區別,他們不會被認為是完全相同的語句。

為什麼有如上說法呢?因為Oracle會將一個SQL轉換為ASCII值,然後利用HASH函式計算其對應的hash值,到Library Cache中找是否有對應於此唯一HASH值的bucket,如果有比較bucket中是否存在該SQL,若沒有則執行硬解析。那麼大小寫的ASCII是不同的,因此要求是case-insensitive。

(5)、Sharable SQL

如果是兩個不同的session發起了完全相同的SQL語句,這也不意味著這個語句是可以共享的。比如說:使用者SCOTT下有一個表EMP,發起了下面的語句:

SELECT ENAME from EMP;

使用者FRED 有一個自己的表也叫EMP並且發起相同的語句:

SELECT ENAME from EMP;

儘管語句完全一樣但是由於需要訪問的EMP表是不同的物件,所以需要對這條語句產生不同的版本。

這裡MOS沒有展開說,實際上這裡說到的兩個使用者,其對應於兩個schema,我們知道不同的schema中有不同的物件,不同schema內的物件若被其它使用者訪問,需要DBA或該使用者賦予相關許可權。另外,SQL硬解析時需要將物件進行名轉換,比如講同義詞轉換為實際的物件,我想這裡SCOTT執行的SELECT ENAME from EMP應該轉換成SELECT ENAME from SCOTT.EMP。因此這兩個SQL是不同的

有很多條件來判斷兩個完全一致的SQL文字是不是真的是完全相同(以至於他們可以被共享),包括:

語句中引用的所有的物件名必須都被解析成實際相同的物件。

發起語句的session中的optimizer相關的引數應該一致。

繫結變數的型別和長度應該是"相似的"。(這裡不做詳細討論,但是型別和長度的不同確實會導致語句被分為不同的版本)

發起語句的NLS (National Language Support)設定必須相同。

(6)、語句的版本

正如之前在'Sharable SQL'中描述的,如果兩個語句字面上完全相同但是又不能被共享,則會對相同的語句產生不同的'version',即版本。如果Oracle要匹配一個包含多個版本的語句,它將不得不檢查每一個版本來看它們是不是和當前被解析的語句完全相同。所以最好用以下方法來避免高版本數(high version count)。

客戶端使用的繫結變數最大長度需標準化。

如果有大量的schema會包含相同名字的物件,那麼避免使用一個相同的SQL語句。比如:SELECT xx FROM MYTABLE; 並且每個使用者都有一個自己的MYTABLE 的情況。

在Oracle 8.1可以將_SQLEXEC_PROGRESSION_COST設定成'0'。

(7)、Library Cache和Shared Pool latches

shared pool latch是用來保護從shared pool中分配和釋放記憶體的關鍵性操作。

Library cache latche(以及Oracle 7.1中的library cache pin latch)是用來保護library cache中的操作。

所有的這些Latch都是潛在的資源爭用的物件,latch gets發生的次數直接受到shared pool中活動(activity)個數的影響,特別是parse操作。任何減少latch gets或者shared pool中活動(activity)個數的嘗試都有助於提高效能和可擴充套件性。


To Be Continued ...

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7192724/viewspace-772342/,如需轉載,請註明出處,否則將追究法律責任。

相關文章