Oracle Tuning總結

tolywang發表於2007-04-16
關於Oracle的效能調整,一般包括兩個方面,一是指Oracle資料庫本身的調整,比如SGA、PGA的最佳化設定,二是連線Oracle的應用程式以及SQL語句的最佳化。做好這兩個方面的最佳化,就可以使一套完整的Oracle應用系統處於良好的執行狀態。



本文主要是把一些Oracle Tuning的文章作了一個簡單的總結,力求以實際可操作為目的,配合講解部分理論知識,使大部分具有一般Oracle知識的使用者能夠對Oracle Tuning有所瞭解,並且能夠根據實際情況對某些引數進行調整。關於更加詳細的知識,請參見本文結束部分所提及的推薦書籍,同時由於該話題內容太多且複雜,本文必定有失之偏頗甚至錯誤的地方,請不吝賜教,並共同進步。
1. SGA的設定
在Oracle Tuning中,對SGA的設定是關鍵。SGA,是指Shared Global Area , 或者是 System Global Area , 稱為共享全域性區或者系統全域性區。



對於SGA區域內的記憶體來說,是共享的、全域性的,在UNIX 上,必須為oracle 設定共享記憶體段(可以是一個或者多個),因為oracle 在UNIX上是多程式;而在WINDOWS上oracle是單程式(多個執行緒),所以不用設定共享記憶體段。

1.1 SGA的各個組成部分

下面用 sqlplus 查詢舉例看一下 SGA 各個組成部分的情況:

SQL> select * from v$sga;

NAME VALUE

-------------------- ----------

Fixed Size 104936

Variable Size 823164928

Database Buffers 1073741824

Redo Buffers 172032

或者

SQL> show sga

Total System Global Area 1897183720 bytes

Fixed Size 104936 bytes

Variable Size 823164928 bytes

Database Buffers 1073741824 bytes

Redo Buffers 172032 bytes

Fixed Size

oracle 的不同平臺和不同版本下可能不一樣,但對於確定環境是一個固定的值,裡面儲存了SGA 各部分元件的資訊,可以看作引導建立SGA的區域。

Variable Size

包含了shared_pool_size、java_pool_size、large_pool_size 等記憶體設定

Database Buffers

指資料緩衝區,在8i 中包含db_block_buffer*db_block_size、buffer_pool_keep、buffer_pool_recycle 三部分記憶體。在9i 中包含db_cache_size、db_keep_cache_size、db_recycle_cache_size、db_nk_cache_size。

Redo Buffers

SQL> select substr(name,1,10) name,substr(value,1,10) value

2 from v$parameter where name = 'log_buffer';

NAME VALUE

-------------------- --------------------

log_buffer 163840

SQL> select * from v$sgastat where pool is null;

POOL NAME BYTES

----------- -------------------------- ----------

fixed_sga 104936

db_block_buffers 1073741824

log_buffer 163840

SQL> select * from v$sga;

NAME VALUE

-------------------- ----------

Fixed Size 104936

Variable Size 823164928

Database Buffers 1073741824

Redo Buffers 172032

172032 – 163840 = 8192

(以上試驗資料是在 HP B.11.11 + Oracle 8.1.7.4 環境下得到的)

1.2 SGA的大小設定

在對SGA的結構進行簡單分析以後,下面是關於如何根據系統的情況正確設定SGA大小的問題。

SGA是一塊記憶體區域,佔用的是系統實體記憶體,因此對於一個Oracle應用系統來說,SGA決不是越大越好,這就需要尋找一個系統最佳化的平衡點。

1.2.1 設定引數前的準備

在設定SGA的記憶體引數之前,我們首先要問自己幾個問題

一:實體記憶體多大

二:作業系統估計需要使用多少記憶體

三:資料庫是使用檔案系統還是裸裝置

四:有多少併發連線

五:應用是OLTP 型別還是OLAP 型別

根據這幾個問題的答案,我們可以粗略地為系統估計一下記憶體設定。那我們現在來逐個問題地討論,首先實體記憶體多大是最容易回答的一個問題,然後作業系統估計使用多少記憶體呢?從經驗上看,不會太多,通常應該在200M 以內(不包含大量程式PCB)。

關於資料庫有多少併發連線,這實際上關係到PGA 的大小(MTS 下還有large_pool_size)。事實上這個問題應該說還跟OLTP 型別或者OLAP 型別相關。對於OLTP型別oracle 傾向於可使用MTS,對於OLAP 型別使用獨立模式,同時OLAP 還可能涉及到大量的排序操作的查詢,這些都影響到我們記憶體的使用。那麼所有的問題綜合起來,實際上主要反映在UGA的大小上。UGA主要包含以下部分記憶體設定

SQL> show parameters area_size

NAME TYPE VALUE

------------------------------------ ------- --------

bitmap_merge_area_size integer 1048576

create_bitmap_area_size integer 8388608

hash_area_size integer 131072

sort_area_size integer 65536

SQL>

在這部分記憶體中我們最關注的通常是sort_area_size,這是當查詢需要排序的時候,資料庫會話將使用這部分記憶體進行排序,當記憶體大小不足的時候,使用臨時表空間進行磁碟排序。由於磁碟排序效率和記憶體排序效率相差好幾個數量級,所以這個引數的設定很重要。

當出現大量排序時的磁碟I/O操作時,可以考慮增加sort_area_size的值。sort_area_size是Oracle用於一次排序所需的最大記憶體數,在排序結束但是結果列返回之前,Oracle會釋放sort_area_size大小的記憶體,但是會保留sort_area_retained_size大小的記憶體,知道最後一行結果列返回以後,才釋放所有的記憶體。

會導致排序的語句有 SELECT DISTINCT , MINUS , INTERSECT , UNION 和 min()、max()、count() 操作;而不會導致排序的語句有 UPDATE , 帶BETWEEN子句的SELECT 等等。

這四個引數都是針對會話進行設定的,是單個會話使用的記憶體的大小,而不是整個資料庫使用的。偶爾會看見有人誤解了這個引數以為是整個資料庫使用的大小,這是極其嚴重的錯誤。假如設定了MTS,則UGA被分配在large_pool_size,也就是說放在了共享記憶體裡面,不同程式(執行緒)之間可以共享這部分記憶體。在這個基礎上,我們假設資料庫存在併發執行server process 為100 個,根據上面我們4 個引數在oracle8.1.7 下的預設值,我們來計算獨立模式下PGA 的大致大小。由於會話並不會經常使用create_bitmap_area_size 、bitmap_merge_area_size,所以我們通常不對四個引數求和。在考慮到除這四個引數外會話所儲存的變數、堆疊等資訊,我們估計為2M,則200 個程式最大可能使用200M 的PGA.
1.2.2 一個經驗公式
現在,根據上面這些假定,我們來看SGA 實際能達到多少記憶體。在1G 的記憶體的伺服器上,我們能分配給SGA 的記憶體大約為400—500M。若是2G 的記憶體,大約可以分到1G的記憶體給SGA,8G 的記憶體可以分到5G的記憶體給SGA。當然我們這裡是以預設的排序部分記憶體sort_area_size=64k進行衡量的,假如我們需要調大該引數和hash_area_size等引數,然後我們應該根據併發的程式的數量,來衡量考慮這個問題。

事實上,通常我們更習慣透過直觀的公式化來表達這樣的問題:

OS 使用記憶體+SGA+併發執行程式數*(sort_area_size+hash_ara_size+2M) < 0.7*總記憶體

(公式是死的,系統是活的,實際應用的調整不必框公式,這不過是一個參考建議)

1.2.3 各個引數的設定

那麼SGA中的各個引數具體應該按照什麼樣的原則來設定呢,下面進行討論:

log_buffer

對於日誌緩衝區的大小設定,通常我覺得沒有過多的建議,因為參考LGWR寫的觸發條件之後,我們會發現通常超過3M意義不是很大。作為一個正式系統,可能考慮先設定這部分為log_buffer=1—3M 大小,然後針對具體情況再調整。

large_pool_size

對於大緩衝池的設定,假如不使用MTS,建議在20—30M 足夠了。這部分主要用來儲存並行查詢時候的一些資訊,還有就是RMAN 在備份的時候可能會使用到。如果設定了MTS,則由於UGA部分要移入這裡,則需要具體根據session最大數量和 sort_ares_size 等相關會話記憶體引數的設定來綜合考慮這部分大小的設定,一般可以考慮為 session * (sort_area_size + 2M)。這裡要提醒一點,不是必須使用MTS,我們都不主張使用MTS,尤其同時線上使用者數小於500的情況下。。

java_pool_size

假如資料庫沒有使用JAVA,我們通常認為保留10—20M大小足夠了。事實上可以更少,甚至最少只需要32k,但具體跟安裝資料庫的時候的元件相關(比如http server)。

shared_pool_size

這是迄今為止最具有爭議的一部分記憶體設定。按照很多文件的描述,這部分內容應該幾乎和資料緩衝區差不多大小。但實際上情況卻不是這樣的。首先我們要考究一個問題,那就是這部分記憶體的作用,它是為了快取已經被解析過的SQL,而使其能被重用,不再解析。這樣做的原因是因為,對於一個新的SQL(shared_pool 裡面不存在已經解析的可用的相同的SQL),資料庫將執行硬解析,這是一個很消耗資源的過程。而若已經存在,則進行的僅僅是軟分析(在共享池中尋找相同SQL),這樣消耗的資源大大減少。所以我們期望能多共享一些SQL,並且如果該引數設定不夠大,經常會出現ora-04031錯誤,表示為了解析新的SQL,沒有可用的足夠大的連續空閒空間,這樣自然我們期望該引數能大一些。但是該引數的增大,卻也有負面的影響,因為需要維護共享的結構,記憶體的增大也會使得SQL 的老化的代價更高,帶來大量的管理的開銷,所有這些可能會導致CPU 的嚴重問題。

在一個充分使用繫結變數的比較大的系統中,shared_pool_size 的開銷通常應該維持在300M 以內。除非系統使用了大量的儲存過程、函式、包,比如oracle erp 這樣的應用,可能會達到500M甚至更高。於是我們假定一個1G記憶體的系統,可能考慮設定該引數為100M,2G 的系統考慮設定為150M,8G 的系統可以考慮設定為200—300M。

對於一個沒有充分使用或者沒有使用繫結變數系統,這可能給我們帶來一個嚴重的問題。所謂沒有使用bind var 的SQL,我們稱為Literal SQL。也就是比如這樣的兩句SQL我們認為是不同的SQL,需要進行2 次硬解析:

select * from EMP where name = ‘TOM’;

select * from EMP where name = ‘JERRY’;

假如把 ’TOM’ 和 ’JERRY’ 換做變數V,那就是使用了bind var,我們可以認為是同樣的SQL 從而能很好地共享。共享SQL 本來就是shared_pool_size 這部分記憶體存在的本意,oracle的目的也在於此,而我們不使用bind var 就是違背了oracle 的初衷,這樣將給我們的系統帶來嚴重的問題。當然,如果透過在作業系統監控,沒有發現嚴重的cpu問題,我們如果發現該共享池命中率不高可以適當的增加shred_pool_size。但是通常我們不主張這部分記憶體超過800M(特殊情況下可以更大)。

事實上,可能的話我們甚至要想辦法避免軟分析,這在不同的程式語言中實現方式有差異。我們也可能透過設定session_cached_cursors 引數來獲得幫助(這將增大PGA)

關於使用繫結變數的話題,在下面的應用最佳化中繼續討論。

Data buffer

現在我們來談資料緩衝區,在確定了SGA 的大小並分配完了前面部分的記憶體後,其餘的,都分配給這部分記憶體。通常,在允許的情況下,我們都嘗試使得這部分記憶體更大。這部分記憶體的作用主要是快取 DB BLOCK,減少甚至避免從磁碟上獲取資料,在8i中通常是由db_block_buffers*db_block_size 來決定大小的。如果我們設定了buffer_pool_keep 和buffer_pool_recycle,則應該加上後面這兩部分記憶體的大小。
可以看出,設定SGA時基本上應該掌握的原則是:

data buffer 一般可以儘可能的大

shared_pool_size 應該適度

log buffer 在 1MB 以內就可以了

假定oracle是 32 bit ,伺服器RAM大於2G ,注意你的PGA的情況,,則建議

shared_pool_size + data buffer +large_pool_size + java_pool_size < 1.6G

再具體化,如果512M RAM

建議 shared_pool_size = 50M, data buffer = 200M

如果1G RAM

shared_pool_size = 100M , data buffer = 500M

如果2G RAM

shared_pool_size = 150M ,data buffer = 1.2G

實體記憶體再大已經跟引數沒有關係了

假定64 bit ORACLE

記憶體4G

shared_pool_size = 200M , data buffer = 2.5G

記憶體8G

shared_pool_size = 300M , data buffer = 5G

記憶體 12G

shared_pool_size = 300M-----800M , data buffer = 8G
1.3 32bit 與 64bit 對SGA的影響
為什麼在上面SGA大小設定的經驗規則中要分 32bit Oracle 和 64bit Oracle 呢,是因為這關係到SGA大小的上限問題。在32bit的資料庫下,通常oracle只能使用不超過1.7G的記憶體,即使我們擁有12G的記憶體,但是我們卻只能使用1.7G,這是一個莫大的遺憾。假如我們安裝64bit的資料庫,我們就可以使用很大的記憶體,幾乎不可能達到上限。但是64bit 的資料庫必須安裝在64bit 的作業系統上,可惜目前windows上只能安裝32bit的資料庫,我們透過下面的方式可以檢視資料庫是 32bit 還是 64bit :

SQL> select * from v$version;

BANNER

----------------------------------------------------------------

Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production

PL/SQL Release 8.1.7.0.0 - Production

CORE 8.1.7.0.0 Production

TNS for 32-bit Windows: Version 8.1.7.0.0 - Production

NLSRTL Version 3.4.1.0.0 – Production

在UNIX平臺下的顯示有所不同,明顯可以看出是 64bit Oracle ,比如在HP-UX平臺上:

SQL> select * from v$version;

BANNER

----------------------------------------------------------------

Oracle8i Enterprise Edition Release 8.1.7.4.0 - 64bit Production

PL/SQL Release 8.1.7.4.0 - Production

CORE 8.1.7.0.0 Production

TNS for HPUX: Version 8.1.7.4.0 - Production

NLSRTL Version 3.4.1.0.0 – Production

32bit的oracle無論跑在32bit或者64bit的平臺都有SGA的限制的,而對於32bit的平臺只能跑32bit的oracle,但是在特定的作業系統下,可能提供了一定的手段,使得我們可以使用超過1.7G 的記憶體,達到2G 以上甚至更多。由於我們現在一般都使用64bit Oracle,因此關於如何在32bit平臺上擴充套件SGA大小的問題不再贅述。

1.4 9i中相關引數的變化

oracle的版本的更新,總是伴隨著引數的變化,並且越來越趨向於使得引數的設定更簡單,因為複雜的引數設定使得DBA們經常焦頭爛額。關於記憶體這部分的變化,我們可以考察下面的引數。事實上在9i中資料庫本身可以給出一組適合當前執行系統的SGA相關部分的引數調整值(參考V$DB_CACHE_ADVICE、V$SHARED_POOL_ADVICE),關於PGA也有相關檢視V$PGA_TARGET_ADVICE 等。

Data buffer

PGA

在9i 裡面這部分也有了很大的變化。在獨立模式下,9i已經不再主張使用原來的UGA相關的引數設定,而代之以新的引數。假如workarea_size_policy=AUTO(預設),則所有的會話的UGA 共用一大塊記憶體,該記憶體由 pga_aggregate_target 設定。在我們根據前面介紹的方法評估了所有程式可能使用的最大PGA 記憶體之後,我們可以透過在初始化引數中設定這個引數,從而不再關心其他 ”*_area_size” 引數。

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

相關文章