Oracle 的 KEEP pool, RECYCLE pool和DEFAULT pool

xz43發表於2010-12-22

Keep Buffer Pool

    Keep Buffer Pool 的作用是快取那些需要經常查詢的物件但又容易被預設緩衝區置換出去的物件,按慣例,Keep pool設定為合理的大小,以使其中儲存的物件不再age out,也就是查詢這個物件的操作不會引起磁碟IO操作,可以極大地提高查詢效能。

    預設的情況下 db_keep_cache_size=0,未啟用,如果想要啟用,需要手工設定db_keep_cache_size的值,設定了這個值之後 db_cache_size 會減少。

    並不是我們設定了keep pool 之後,熱點表就一定能夠快取在 keep pool ,keep pool 同樣也是由LRU 連結串列管理的,當keep pool 不夠的時候,最先快取到 keep pool 的物件會被擠出,不過與default pool 中的 LRU 的管理方式不同,在keep pool 中表永遠是從MRU 移動到LRU,不會由於你做了FTS而將表快取到LRU端,在keep pool中物件永遠是先進先出。

    10g中SGA自動管理,ORACLE並不會為我們管理keep pool ,ORACLE只會管理default pool。

    檢視 keep pool 大小

SQL> select component,current_size from v$sga_dynamic_components
  2  where component='KEEP buffer cache';

COMPONENT                                                        CURRENT_SIZE
---------------------------------------------------------------- ------------
KEEP buffer cache                                                           0


   手動分配keep pool

SQL> show parameter keep

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
buffer_pool_keep                     string
control_file_record_keep_time        integer     7
db_keep_cache_size                   big integer 0

SQL> alter system set db_keep_cache_size=10m;

系統已更改。

SQL> show parameter keep

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
buffer_pool_keep                     string
control_file_record_keep_time        integer     7
db_keep_cache_size                   big integer 16M 這裡keep pool 16M,可我前面設定命名是10m了?

SQL> select component,current_size from v$sga_dynamic_components where component='KEEP buffer cache';

COMPONENT                                                        CURRENT_SIZE
---------------------------------------------------------------- ------------
KEEP buffer cache                                                    16777216    
這裡keep pool 16M,可我前面設定命名是10m了?


    檢視keep pool剩餘大小

SQL> select p.name,a.cnum_repl "total buffers",a.anum_repl "free buffers" from x$kcbwds a, v$buffer_pool p
  2  where a.set_id=p.LO_SETID and     p.name='KEEP';

NAME                 total buffers free buffers
-------------------- ------------- ------------
KEEP                          1984         1984
  可以看到沒有使用過keep 池

    指定table的快取池

SQL>create table test  as select * from dba_objects;;

Table created.
SQL> alter table test storage(buffer_pool keep);

Table altered.

或者是

create table test storage(buffer_pool keep) as select * from dba_objects;

檢視放入Keep的物件

SQL> select segment_name from dba_segments where BUFFER_POOL = 'KEEP';

SEGMENT_NAME
--------------------------------------------------------------------------------
TEST

SQL> /

NAME                 total buffers free buffers
-------------------- ------------- ------------
KEEP                          1984         1962      可以看到使用了22個block

檢視以上的表佔用了db_keep_cache_size 多大的空間?

SQL> select substr(sum(b.NUMBER_OF_BLOCKS) * 8129 / 1024 / 1024, 1, 5) || 'M'
  from (SELECT o.OBJECT_NAME, COUNT(*) NUMBER_OF_BLOCKS
          FROM DBA_OBJECTS o, V$BH bh, dba_segments dd
         WHERE o.DATA_OBJECT_ID = bh.OBJD
           AND o.OWNER = dd.owner
           and dd.segment_name = o.OBJECT_NAME
           and dd.buffer_pool != 'DEFAULT'
         GROUP BY o.OBJECT_NAME
         ORDER BY COUNT(*)) b;  2    3    4    5    6    7    8    9 

SUBSTR(SUM(
-----------
3.643M

SQL> select table_name,cache,blocks from dba_tables where wner='ROBINSON' and buffer_pool='KEEP';

TABLE_NAME                     CACHE                    BLOCKS
------------------------------ -------------------- ----------
TEST                               N                        22        

可以看到這個表的 22個block 全部cache 到 keep pool ,這裡的cache 欄位表明 這個表 還沒有使用 這個命令 alter table  test  cache,如果 使用了 alter table test cache ,命令,那麼 N 將變成Y

總結:如果表經常使用,而且表較小,可以設定 keep pool ,將table 全部 cache 到 keep pool, keep pool 要麼 全部 cache 一個table ,要麼 不cache 。所以,對於大表來說,如果想要 cache 到 keep pool, 就需要設定 較大的 keep pool ,以容納 大的 table,否者就沒有作用了。

Recycle Buffer Pool

Recycle Buffer Pool正好相反。Recycle Buffer Pool用於儲存臨時使用的、不被經常使用的較大的物件,這些物件放置在Default Buffer Pool顯然是不合適的,這些塊會導致過量的緩衝區重新整理輸出,而且不會帶來任何好處,因為等你想要再用這個塊時,它可已經老化退出了快取。要把這些段與預設池和保持池中的段分開,這樣就不會導致預設池和保持池中的塊老化而退出快取。

SQL> show parameter recyc

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
buffer_pool_recycle                  string
db_recycle_cache_size                big integer 12M
recyclebin                           string      on

如何將一個表放入Recycle Buffer Pool中:

SQL> alter table test1 storage (buffer_pool recycle);

Table altered.


很多老的文件會提及buffer_pool_keep和buffer_pool_recycle 這兩個引數,其實這兩個引數已經廢棄,由新引數db_keep_cache_size和db_recycle_cache_size 替代:

SQL>select ISDEPRECATED,NAME from v$parameter where name = 'buffer_pool_keep';

ISDEP NAME
----- -----------------
TRUE  buffer_pool_keep


--表快取   

alter table ..... storage(buffer_pool keep);     

--檢視哪些表被放在快取區 但並不意味著該表已經被快取   

select table_name from dba_tables where buffer_pool='keep';   

--查詢到該表是否已經被快取   

select table_name,cache,buffer_pool from user_TABLES where cache like '%Y';   

--已經加入到KEEP區的表想要移出快取,使用   

alter table table_name nocache;   

--批次插入ORACLE建議用 

insert all into ... insert into  ... select  1 from dual;  

insert all into ... insert into ...select 1 from dual;   

--查詢當前使用者下表的情況   

select table_name,cache,buffer_pool from user_TABLES;   

--對於普通LOB型別的segment的cache方法   

alter table t2 modify lob(c2) (storage (buffer_pool keep) cache);   

--取消快取   

alter table test modify lob(address) (storage (buffer_pool keep) nocache);   

--查詢段   

select segment_name,segment_type,buffer_pool from user_segments;   

--對基於CLOB型別的物件的cache方法     

alter table lob1 modify lob(c1.xmldata) (storage (buffer_pool keep) cache);    

  --查詢該使用者下所有表內的大欄位情況   

select column_name,segment_name from user_lobs;

 

來一段Tom關於Multiple Buffer Pools的解釋,講解得很清楚:

實際上,這3 個池會以大體相同的方式管理塊;將塊老化或快取的演算法並沒有根本的差異。這樣做的目標是讓DBA 能把段聚集到“熱”區(hot)、“溫”區(warm)和“不適合快取”區(do not care to cache)。

理論上講,預設池中的物件應該足夠熱(也就是說,用得足夠多),可以保證一直呆在快取中。快取會把它們一直留在記憶體中,因為它們是非常熱門的塊。可能還有 一些段相當熱門,但是並不太熱;這些塊就作為溫塊。這些段的塊可以從快取重新整理輸出,為不常用的一些塊(“不適合快取”塊)騰出空間。為了保持這些溫段的塊得到快取,可以採取下面的某種做法:將這些段分配到保持池,力圖讓溫塊在緩衝區快取中停留得更久。將“不適合快取”段分配到回收池,讓回收池相當小,以便塊能快速地進入快取和離開快取(減少管理的開銷)。這樣會增加DBA 所要執行的管理工作,因為要考慮3 個快取,要確定它們的大小,還要為這些快取分配物件。還要記住,這些池之間沒有共享,所以,如果保持池有大量未用的空間,即使預設池或回收池空間不夠用了, 保持池也不會把未用空間交出來。總之,這些池一般被視為一種非常精細的低階調優裝置,只有所有其他調優手段大多用過之後才應考慮使用。

按以上步驟把表storage到keep pool中,然後呼叫alter system flush buffer_cache清空快取,再全表掃描該表並開啟執行計劃跟蹤,發現有physical reads,如下:
第一次執行計劃如下:
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        253  consistent gets
        251  physical reads
          0  redo size
        520  bytes sent via SQL*Net to client
        469  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
第二次執行計劃如下:
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        253  consistent gets
          0  physical reads
          0  redo size
        520  bytes sent via SQL*Net to client
        469  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

 
不知道是否可以這樣理解:對於storage到keep pool中的表,第一次會直接physical reads 到keep pool中,下次就直接從keep pool中讀了。flush buffer_cache會清空keep pool,這個試驗就可以證明。
像上面這樣連續執行2次再看執行計劃,和不設定keep pool時的執行計劃應該一樣的,因為讀第二次時,也是從default cache中讀。但是當我們多讀幾個大表到buffer cache後,也就是替換原來從default cache中讀取的資料後,再去讀放入keep中的表時,就會發現keep確實起作用了,唉,終於明白怎麼一回事,害得我為flush buffer導致keep中的表也phisical鬱悶了半天。

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

相關文章