oracle實例的內存(SGA和PGA)調整,優化之原理和方法

一、SGA與PGA的結構:

SGA
查看SGA:
Sqlp> show sga
或 select * from v$sga;
Total System Global Area  289406976 bytes
Fixed Size                  1248600 bytes
Variable Size             176161448 bytes
Database Buffers          109051904 bytes
Redo Buffers                2945024 bytes

Fixed Size:包括了數據庫與實例的控制信息、狀態信息、字典信息等,啓動時就被固定在SGA中,不會改變。
Variable Size:包括了shard pool、large pool、java pool、stream pool、遊標區和其他結構
Database Buffers:數據庫中數據塊緩衝的地方,是SGA中最大的地方,決定數據庫性能
Redo Buffers:提供REDO緩衝的地方,在OLAP中不需要太大

V$sgastat記錄了SGA的一些統計信息
V$sga_dynamic_components 保存SGA中可以手動調整的區域的一些調整記錄

Shard pool:
Shard_pool_size決定其大小,10g以後 自動管理
Shard_pool中數據字典和控制區結構用戶無法直接控制,與用戶有關的只有sql緩衝區(library cache)。
將 經常訪問的過程或包用DBMS_SHARED_POOL.KEEP存儲過程將該包pin在共享池中。
手工清除共享池的內容:alter system flush shard_pool;

共享池相關的幾個常用的視圖:
V$sqlarea 記錄了所有sql的統計信息,包括執行次數、物理讀、邏輯讀、耗費時間等
V$sqltext_with_newline 完全顯示sql語句,通過hash_value來標示語句,piece排序
V$sql_plan保存了sql的執行計劃,通過工具查看
V$shared_pool_advice 對共享池的預測,可以做調整SGA的參考
SGA:System Global Area是Oracle Instance的基本組成部分,在實例啓動時分配;
     系統全局域SGA主要由三部分構成:共享池、數據緩衝區、日誌緩衝區。

(1)共享池:Shared Pool用於緩存最近被執行的SQL語句和最近被使用的數據定義,
        主要包括:Library cache(共享SQL區)和Data dictionary cache(數據
         字典緩衝區).共享SQL區是存放用戶SQL命令的區域,數據字典緩衝區存
         放數據庫運行的動態信息.不管Oracle是32 bit 還是 64 bit 的,假定應用存在沒有很好的使用綁定變量的情況,也不能設置 shared_pool_size 過大,通常應該控制在100M--200M,除非是 ORACLE ERP 一類的使用了很多存儲過程函數、包 ,這樣的很大的系統,可以考慮增大shared_pool_size,但是如果超過500M可能是危險的,達到1G幾乎就會造成CPU的嚴重負擔,系統甚至癱瘓。所以shared_pool_size 如果超過200M還命中率不高,那麼應該從應用上找原因而不是一味的增加內存,shared_pool_size 過大主要增加了管理負擔和latch 的開銷。
 
(2) 緩衝區高速緩存:Database Buffer Cache用於緩存從數據文件中檢索出來的數據
 塊,可以大大提高查詢和更新數據的性能,通常可以儘可能的大。
Oracle把從data buffer中獲得的數據庫叫cache hit,把從磁盤獲得的腳cache miss
數據緩衝 區中的數據塊通過髒列表(dirty list)和LRU列表(LRU list)來管理。
 Data buffer可細分爲:default pool、keep pool、recycle pool對應的參數爲db_cache_size、 db_keep_cache_size 、db_recycle_size分別表示緩衝區大小
 從9i開始oracle支持不同塊大小的 表空間,相應的可以爲不同塊大小的表空間指定不同塊大小的數據緩衝區,不同塊大小的數據緩衝區可以用相應的db_nk_cache_size來指定,其中 n可以是2、4、6、16或32
 V$db_cache_advice 對數據緩衝區的預測,可以做調整data buffer的參考
 V$bh、 x$bh記錄了數據塊在data buffer中緩衝的情況,通過這個視圖可以找系統中的熱點塊。通過下面語句找系統中top 10 熱點快所在的熱點對象:

Select /*+ rule*/ owner,object_name from dba_objects
Where data_object_id in
(select obj from
(select obj from x$bh order by tch desc)
Where rownum<11);

(3)大型池:Large Pool是SGA中一個可選的內存區域,它只用於shared server環境
 
(4)Java池:ava Pool爲Java命令的語法分析提供服務

PGA:Program Global Area是爲每個連接到Oracle database的用戶進程保留的內存。用來保存於用戶進程相 關的內存段。


自動內存管理:

 從9i開始使用PGA自動管理,pga_aggregate_target參數指定session一共使用的最大PGA內存的上限。 Workarea_size_policy參數用於開關PGA內存自動管理功能,auto/manual.在OLTP環境中,自動PGA 管理只要設置到一定的值,如2G左右就能滿足系統的要求。
 sql>Alter system set pga_aggregate_target=1000m scope=both;
 
  從9i開始,sga_max_size參數設置SGA 的內存大小,不能動態修改
從10g開始,指定了sga_target參數後,所有的SGA組件如:shared pool、 data buffer、 large pool都不用手工指定了,Oracle會自動管理。這一特性就是自動共享內存管理ASMM。如果設置了sga_target=0,就自動關閉自動共享內 存管理功能。Sga_target大小不能超過sga_max_size的大小。
 
 在Oracle 10g中引入了自動SGA內存管理特性,DBA可以設定SGA_TARGET告訴Oracle可用的SGA內存爲多大,由Oracle根據系統負載來動態調整各組件大小,相應的數定會保存在控制文件中,使數據庫重啓後也記得各組件大小。

需要注意一下幾點:
要使用自動SGA內存管理,STATISTICS_LEVEL參數必須設爲TYPICAL或ALL,系統自動收集相應的信息用來動態調整SGA設定。

可以設定某個組件的值,Oracle SGA使用此值爲該組件的最小大小
可動態調整的參數:
DB_CACHE_SIZE,SHARED_POOL_SIZE,LARGE_POOL_SIZE,JAVA_POOL_SIZE。

需手動設置的參數:
LOG_BUFFER,STREAMS_POOL,DB_NK_CACHE_SIZE,DB_KEEP_CACHE_SIZE,DB_RECYCLE_CACHE_SIZE。

手動管理SGA:

alter system set sga_max_size=1600M  scope=spfile;需重啓數據庫生效
Alter system set sga_target=2000m;
Alter system set db_cache_size=1000m;
Alter system set shared_pool=200m;
Alter system set sga_target=0---------關閉自動共享內存管理ASMM

11G以後sga+pga整個內存可以自動管理AMM,相關 參數memory_max_target  memory_target.設置好這兩個參數後就不用關心SGA和PGA了

Alter system set memory_target=3000m SCOPE=SPFILE;
Alter system set memory_max_target=4000M SCOPE=SPFILE;  
ALTER SYSTEM SET PGA_AGGREGATE_TARGET=0 SCOPE=SPFILE;
ALTER SYSTEM SET SGA_TARGET=0 SCOPE=SPFILE;

11g手動內存管理:
Alter system set memory_target=3000m;
Alter system set sga_target=2000m;
Alter system set pga_aggregate_target=1000m;
Alter system set memory_target=0;---------關閉自動內存管理AMM

二、分析與調整:

1、系統全局域:
SGA與操作系統、內存大小、cpu、同時登錄的用戶數有關。可佔OS系統物理內存的1/2到1/3,當然,如果服務器上只有oracle的話,可以分配的更大一些,如果還有其他服務,如IIS等,那就要分的小一些。
  
  1、共享池:
  修改共享池的大小,ALTER SYSTEM SET SHARED_POOL_SIZE = 64M;
  查看共享SQL區的使用率: 
select(sum(pins-reloads))/sum(pins) "Library cache" from v$librarycache;
這個使用率應該在90%以上,否則需要增加共享池的大小。
  查看數據字典緩衝區的使用率:
select (sum(gets-getmisses-usage-fixed))/sum(gets) "Data dictionary cache" from v$rowcache;
這個使用率也應該在90%以上,否則需要增加共享池的大小。
  
   2、緩衝區高速緩存:它的大小要根據數據量來決定,在OLTP系統中要求data buffer 的命中率在95%以上.
SGA=((db_block_buffers * block size+shared_pool_size+large_pool_size+java_pool_size+log_buffers)+1MB
查看數據庫數據緩衝區的使用情況:

 SELECT name,value FROM v$sysstat order by name WHERE name IN(''DB BLOCK GETS'',''CONSISTENT GETS'',''PHYSICAL READS''); 
 計算出來數據緩衝區的使用命中率=1-(physical reads/(db block gets+consistent gets)),這個命中率應該在90%以上,否則需要增加數據緩衝區的大小。
SQL>select sum(pins) "請求存取數",sum(reloads) "不命中數",sum(reloads)/sum(pins) from v$librarycache  
  其中,pins,顯示在庫高速緩存中執行的次數;reload,顯示在執行階段庫高速緩存不命中的數目,一般 sum(reloads)/sum(pins)的值應接近於零.如果大於1%就應該增加shared_pool_size的值, 來提高數據字典高速緩存可用的內存數量,減少不命中數.
  通過動態性能表v$rowcache來查詢數據字典高速緩存的活動:  
select sum(gets) "請求存取數",sum(getmisses) "不命中數" from v$rowcache;   
 其中,gets,顯示請求相應項的總數; getmisses,顯示造成高速緩存不命中的數據請求數.   
 Hit ratio與wait events:
SQL>select value from $pgastat where name =''cache hit percentage'';
 Hit ratio與wait events是此消彼漲,在執行類似於
SQL>select col1,col2,.. from tab1 a where exists (select 1 from tab2 where a.col3 = b.col3) where ....
 的語句的時候,如果tab1的記錄很多的話,你會發現系統的hit ratio會有很大的提高,wait events是否會改觀呢.

   3、日誌緩衝區
  SELECT name, value  FROM v$sysstat WHERE name IN (''redo entries'',''redo log space requests'')
查看日誌緩衝區的使用情況。
查詢出的結果可以計算出日誌緩衝區的申請失敗率:     
 申請失敗率=requests/entries,申請失敗率應該接近於0,否則說明日誌緩衝區開設太小,需要增加ORACLE數據庫的日誌緩衝區。

   4、大型池:
可以減輕共享池的負擔;可以爲備份、恢復等操作來使用;不使用LRU算法來管理
其大小由數據庫的‘共享模式/db模式’如果是共享模式的話,要分配的大一些
 指定Large Pool的大小,
ALTER SYSTEM SET LARGE_POOL_SIZE=64M
  
  5、Java池:
  在安裝和使用Java的情況下使用


三.如何估算PGA,SGA的大小,配置數據庫服務器的內存
ORACLE給的建議是: 一個數據庫服務器,分80%的內存給數據庫,20%的內存給操作系統.
OLTP系統  PGA=(Total Memory)*80%*20%。餘下SGA。
DSS系統 PGA=(Total Memory)*80%*70%。 餘下SGA。
混合系統 PGA=(Total Memory)*80%*50%。餘下SGA。
 
PGA:
SQL> select * from v$pgastat; 
NAME                                                                  VALUE UNIT
---------------------------------------------------------------- ---------- ------------
aggregate PGA target parameter                                    104857600 bytes  
-----這個值等於參數PGA_AGGREGATE_TARGET的值,如果此值爲0,表示禁用了PGA自動管理。
aggregate PGA auto target                                          75220992 bytes      
-----表示PGA還能提供多少內存給自動運行模式,通常這個值接近pga_aggregate_target-total pga inuse.
global memory bound                                                20971520 bytes 
-----工作區執行的最大值,如果這個值小於1M,馬上增加PGA大小
total PGA inuse                                                    30167040 bytes 
-----當前分配PGA的總大小,這個值有可能大於PGA,如果PGA設置太小.這個值接近
total PGA allocated                                                52124672 bytes 
-----工作區花費的總大小
maximum PGA allocated                                              67066880 bytes
total freeable PGA memory                                                 0 bytes         ----沒有了空閒的PGA
process count                                                            23                    ----當前一個有23個process
max processes count                                                      25 
PGA memory freed back to OS                                               0 bytes
total PGA used for auto workareas                                   8891392 bytes
maximum PGA used for auto workareas                                22263808 bytes
total PGA used for manual workareas                                       0 bytes                  ---爲0自動管理
maximum PGA used for manual workareas                                     0 bytes            ---爲0自動管理
over allocation count                                                     0        
如果PGA設置太小,導致PGA有時大於PGA_AGGREGATE_TARGET的值,此處爲0,說明PGA沒有擴展大於TARGET的值,如 果此值出現過,那麼增加PGA大小。
bytes processed                                                   124434432 bytes
extra bytes read/written                                                  0 bytes
cache hit percentage                                                    100 percent  ---命中率爲100%,如果太小增加PGA 
recompute count (total)                                                6651 
19 rows selected

SQL> select max(pga_used_mem)/1024/1024 M from v$process;   ----當前一個process消耗最大的內存 
M
----------
9.12815189 
SQL> select min(pga_used_mem)/1024/1024 M from v$process where pga_used_mem>0; ---process消耗最少內存 
M
----------
0.19186878 
SQL> select max(pga_used_mem)/1024/1024 M from v$process ;    ----process曾經消耗的最大內存 
M
----------
9.12815189 
SQL> select sum(pga_used_mem)/1024/1024 from v$process;   ----當前process一共消耗的PGA 
SUM(PGA_USED_MEM)/1024/1024
---------------------------
28.8192501068115

如何設置PGA呢?我們可以在壓力測試階段,模擬一下系統的運行,然後運行 
select (select sum(pga_used_mem)/1024/1024 from v$process) /(select count(*) from v$process) from dual;
得到一個process大約佔用了多少的內存,然後估算系統一共會有多少連接,比如一共有500個連接, 
如果processes=450,那麼Sessions=1.1*process +5=500,,再乘以一個process需要消耗的內存,就能大約估算出PGA需要設置多大。 
最好將PGA設置的值比計算出的值大一點,PGA值設定好後,就可以根據系統的性質,如果系統爲OLTP,那麼總的內存可以設置爲 PGA/0.16,最後也能估算出SGA的大小

下面摘抄eygle的關於一個process能夠分配的最大內存(串行操作)的規則: 
10gR1之前,對於串行操作(非並行)一個process能夠分配的最大的內存爲 min(5%pga_aggregate_target,100m) 
10gR2之後,對於串行操作(非並行)一個process能夠分配的最大內存有如下規則: 
如果pga_aggregate_target<=500m,那麼最大的內存爲20%*pga_aggregate_target. 
如果500m<pga_aggregate_target<=1000m,那麼最大內存爲100m. 
如果1000m<pga_aggregate_target<=2.5G,那麼最大內存爲 10%*pga_aggregate_target.
如果pga_aggregate_target>2.5G,那麼最大內存爲2.5G.
就是在非並行方式下,“期望尺寸”爲min(5%*pga_aggregate_target,50%*_pga_max_size,_smm_max_size).

SQL>select ksppinm, ksppstvl, ksppdesc from x$ksppi x, x$ksppcv y where x.indx = y.indx and ksppinm in ('_pga_max_size','_smm_max_size');
SQL> 
NAME                                                                             VALUE                                                                            DESCRIB
-------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
_smm_max_size (kbyte)                                                                   20480                                                                            maximum work area size in auto mode (serial)

SQL> show parameter pga
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target                 big integer 100M

此處一個process能夠分配的最大內存爲20M,因爲我的PGA=100M,符合上面的規則。
隱含參數_smm_max_size表示一個process能夠分配最大的memory.


SGA:
1、Shared pool tunning
Shared pool的優化應該放在優先考慮,因爲一個cache miss在shared pool中發生比在data buffer中發生導致的成本更高,由於dictionary數據一般比library cache中的數據在內存中保存的時間長,所以關鍵是library cache的優化。
Gets:(parse)在namespace中查找對象的次數;
Pins:(execution)在namespace中讀取或執行對象的次數;
Reloads:(reparse)在執行階段library cache misses的次數,導致sql需要重新解析。

1) 檢查v$librarycache中sql area的gethitratio是否超過90%,如果未超過90%,應該檢查應用代碼,提高應用代碼的效率。
Select gethitratio from v$librarycache where namespace='SQL AREA';

2) v$librarycache中reloads/pins的比率應該小於1%,如果大於1%,應該增加參數shared_pool_size的值。
Select sum(pins) executions,sum(reloads) cache_misses,sum(reloads)/sum(pins) from v$librarycache;
reloads/pins>1%有兩種可能,一種是library cache空間不足,一種是sql中引用的對象不合法。

3)shared pool reserved size一般是shared pool size的10%,不能超過50%。V$shared_pool_reserved中的request misses=0或沒有持續增長,或者free_memory大於shared pool reserved size的50%,表明shared pool reserved size過大,可以壓縮。

4)將大的匿名pl/sql代碼塊轉換成小的匿名pl/sql代碼塊調用存儲過程。

5)從9i開始,可以將execution plan與sql語句一起保存在library cache中,方便進行性能診斷。從v$sql_plan中可以看到execution plans。

6)保留大的對象在shared pool中。大的對象是造成內存碎片的主要原因,爲了騰出空間許多小對象需要移出內存,從而影響了用戶的性能。因此需要將一些常用的大的對象保留在shared pool中,下列對象需要保留在shared pool中:
a. 經常使用的存儲過程;
b. 經常操作的表上的已編譯的觸發器
c. Sequence,因爲Sequence移出shared pool後可能產生號碼丟失。
查找沒有保存在library cache中的大對象:
Select * from v$db_object_cache where sharable_mem>10000 and type in ('PACKAGE','PROCEDURE','FUNCTION','PACKAGE BODY') and kept='NO';
將這些對象保存在library cache中:
Execute dbms_shared_pool.keep(‘package_name’);
對應腳本:dbmspool.sql

7)查找是否存在過大的匿名pl/sql代碼塊。兩種解決方案:
A.轉換成小的匿名塊調用存儲過程
B.將其保留在shared pool中
查找是否存在過大的匿名pl/sql塊:
Select sql_text from v$sqlarea where command_type=47 and length(sql_text)>500;

8)Dictionary cache的 優化 
避免出現Dictionary cache的misses,或者misses的數量保持穩定,只能通過調整shared_pool_size來間接調整dictionary cache的大小。
Percent misses應該很低:大部分應該低於2%,合計應該低於15%
Select sum(getmisses)/sum(gets) from v$rowcache;
若超過15%,增加shared_pool_size的值。


2、Buffer Cache

1)granule大小的設置,db_cache_size以字節爲單位定義了default buffer pool的大小。
如果SGA<128M,granule=4M,否則granule=16M,即需要調整sga的時候以granule爲單位增加大小,並且sga的大小應該是granule的整數倍。

2) 根據v$db_cache_advice調整buffer cache的大小
SELECT size_for_estimate,buffers_for_estimate,estd_physical_read_factor,estd_physical_reads FROM v$db_cache_advice WHERE NAME='DEFAULT' AND advice_status='ON' AND block_size=(SELECT Value FROM v$parameter WHERE NAME='db_block_size');
estd_physical_read_factor<=1

3) 統計buffer cache的cache hit ratio>90%,如果低於90%,可以用下列方案解決:
增加buffer cache的值;
使用多個buffer pool;
Cache table;
爲 sorting and parallel reads 建獨立的buffer cache;
SELECT NAME,value FROM v$sysstat WHERE NAME IN ('session logical reads','physical reads','physical reads direct','physical reads direct(lob)');
Cache hit ratio=1-(physical reads-physical reads direct-physical reads direct (lob))/session logical reads;
Select 1-(phy.value-dir.value-lob.value)/log.value from v$sysstat log, v$sysstat phy, v$sysstat dir, v$sysstat LOB where log.name='session logical reads' and phy.name='physical reads' and dir.name='physical reads direct' and lob.name='physical reads direct (lob)';
影響cache hit ratio的因素:
全表掃描;應用設計;大表的隨機訪問;cache hits的不均衡分佈

4)表空間使用自動空間管理,消除了自由空間列表的需求,可以減少數據庫的競爭

3、其他SGA對象
1)redo log buffer
對應的參數是log_buffer,缺省值與 OS相關,一般是500K。檢查v$session_wait中是否存在log buffer wait,v$sysstat中是否存在redo buffer allocation retries
A、檢查是否存在log buffer wait:
Select * from v$session_wait where event='log buffer wait';
如果出現等待,一是可以增加log buffer的大小,也可以通過將log 文件移到訪問速度更快的磁盤來解決。
B、Select name,value from v$sysstat where name in (‘redo buffer allocation retries’,’redo entries’)
Redo buffer allocation retries接近0,小於redo entries 的1%,如果一直在增長,表明進程已經不得不等待redo buffer的空間。如果Redo buffer allocation retries過大,增加log_buffer的值。
C、檢查日誌文件上是否存在磁盤IO競爭現象
Select event,total_waits,time_waited,average_wait from v$system_event where event like ‘log file switch completion%’;
如果存在競爭,可以考慮將log文件轉移到獨立的、更快的存儲設備上或增大log文件。
D、檢查點的設置是否合理
檢查alert.log文件中,是否存在‘checkpoint not complete’;
Select event,total_waits,time_waited,average_wait from v$system_event where event like ‘log file switch (check%’;
如果存在等待,調整log_checkpoint_interval、log_checkpoint_timeout的設置。
E、檢查log archiver的工作
Select event,total_waits,time_waited,average_wait from v$system_event where event like ‘log file switch (arch%’;
如果存在等待,檢查保存歸檔日誌的存儲設備是否已滿,增加日誌文件組,調整log_archiver_max_processes。
F、DB_block_checksum=true,因此增加了性能負擔。(爲了保證數據的一致性,oracle的寫數據的時候加一個checksum在block上,在讀數據的時候對checksum進行驗證)

2)java pool
對於大的應用,java_pool_size應>=50M,對於一般的java存儲過程,缺省的20M已經夠用了。

3)檢查是否需要調整DBWn
Select total_waits from v$system_event where event=’free buffer waits’;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章