一、引言:
有時候一些基礎表需要非常的頻繁訪問,尤其是在一些循環中,對該表中的訪問速度將變的非常重要。為了提高系統的處理性能,可以考慮將一些表及索引讀取並保存到內存中。
二、關於keep內存的幾個參數
下面了解一下具體和CACHE有關的幾個概念,即DB_CACHE中的幾個pool:
DB_CACHE_SIZE:指定缺省的buffer pool的大小,以字節為單位。
DB_KEEP_CACHE_SIZE:指定keep buffer pool的大小,以字節為單位。
DB_RECYCLE_CACHE_SIZE:指定recycle 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中對象永遠是先進先出。
Recycle Buffer Pool
Recycle Buffer Pool正好相反。Recycle Buffer Pool用於存儲臨時使用的、不被經常使用的較大的對象,這些對象放置在Default Buffer Pool顯然是不合適的,這些塊會導致過量的緩沖區刷新輸出,而且不會帶來任何好處,因為等你想要再用這個塊時,它可已經老化退出了緩存。要把這些段與默認池和保持池中的段分開,這樣就不會導致默認池和保持池中的塊老化而退出緩存。
2.1、查看keep pool剩余大小:
1 SQL> conn /as sysdba 2 已連接。 3 4 select p.name,a.cnum_repl "total buffers",a.anum_repl "free buffers" 5 from x$kcbwds a, v$buffer_pool p 6 3 where a.set_id=p.LO_SETID and p.name='KEEP'; 7 8 NAME total buffers free buffers 9 -------------------- ------------- ------------ 10 KEEP 12400 12400
2.2、查看當前keep pool的大小:
1 select component,current_size from v$sga_dynamic_components 2 2 where component='KEEP buffer cache'; 3 4 COMPONENT CURRENT_SIZE 5 ---------------------------------------------------------------- ------------ 6 KEEP buffer cache 104857600
2.3、修改表或索引的結構
要把表cache到內存中,要為表或索引指定buffer pool的類型。具體語句如下:
----修改數據庫表的存儲屬性pool
alter table xxx storage(buffer_pool keep);
又如:
CREATE INDEX cust_idx ... STORAGE (BUFFER_POOL KEEP);
ALTER TABLE customer STORAGE (BUFFER_POOL KEEP);
ALTER INDEX cust_name_idx STORAGE (BUFFER_POOL KEEP);
同時要修改表的cache屬性:
Alter table xxx cache;
也可以在表創建時直接指定相應的屬性:
create table aaa(i int) storage (buffer_pool keep);
create table bbb(i int) storage (buffer_pool keep) cache;
觀察表的cache情況及大小:
select table_name,cache,blocks from user_tables where buffer_pool='KEEP';
2.4、進行全表掃描,將表移入內存:
可以使用ANALYZE table xxx ESTIMATE STATISTICS分析表,使表讀入到keep pool中。也可以使用其它的如全表掃描的語句達到相同的目的。如select * from xxx;
要想驗證是否已經cache到pool中,可以打開執行計划,看具體的物理讀的次數,若已經cache,則物理讀為0.
storage到keep pool中的表,第一次會直接physical reads到keep pool中,下次就直接從keep pool中讀了。但flush buffer_cache會清空keep pool。
三、具體實例:
實驗前提:必須保證db_keep_cache_size值不為0,所以首先有如下操作:
1 -- ----此處只是做實驗,所以設置為100M。 2 SQL> alter system set db_keep_cache_size=100M; 3 4 系統已更改。 5 6 SQL> drop table jack purge; 7 drop table jack purge 8 * 9 第 1 行出現錯誤: 10 ORA-00942: 表或視圖不存在 11 12 13 SQL> create table jack as select * from dba_objects; 14 15 表已創建。 16 SQL> create index indx_object_id on jack(object_id); 17 18 索引已創建。 19 ----未執行Keep命令,通過如下查詢出BFFUER_POOL列值為DEFAULT,表示未KEEP。---- 20 SQL> select BUFFER_POOL from user_tables where TABLE_NAME='JACK'; 21 22 BUFFER_ 23 ------- 24 DEFAULT 25 26 SQL> select BUFFER_POOL from user_indexes where INDEX_NAME='INDX_OBJECT_ID'; 27 28 BUFFER_ 29 ------- 30 DEFAULT 31 32 SQL> alter index indx_object_id storage(buffer_pool keep); 33 34 索引已更改。 35 ----以下將索引全部讀進內存---- 36 SQL> select /*+index(jack,indx_object_id)*/ count(*) from jack where object_id is not null; 37 38 COUNT(*) 39 ---------- 40 72531 41 42 SQL> alter table jack storage(buffer_pool keep); 43 44 表已更改。 45 ----以下將數據全部讀進內存---- 46 SQL> select /*+full(jack)*/ count(*) from jack; 47 48 COUNT(*) 49 ---------- 50 72531 51 ----執行KEEP操作之后,通過如下查詢出BUFFER_POOL列值為KEEP,表示已經KEEP成功了。 52 SQL> select BUFFER_POOL from user_tables where TABLE_NAME='JACK'; 53 54 BUFFER_ 55 ------- 56 KEEP 57 58 SQL> select BUFFER_POOL from user_indexes where INDEX_NAME='INDX_OBJECT_ID'; 59 60 BUFFER_ 61 ------- 62 KEEP
附錄:與cache到內存相關的命令
--表緩存
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;
--查詢當前用戶下表的情況
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;
