一、引言:

    有时候一些基础表需要非常的频繁访问,尤其是在一些循环中,对该表中的访问速度将变的非常重要。为了提高系统的处理性能,可以考虑将一些表及索引读取并保存到内存中。

二、关于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_components2   2      where component='KEEP buffer cache';3 4 COMPONENT                             CURRENT_SIZE5 ---------------------------------------------------------------- ------------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 DEFAULT25 26 SQL> select BUFFER_POOL from user_indexes where INDEX_NAME='INDX_OBJECT_ID';27 28 BUFFER_29 -------30 DEFAULT31 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      7253141 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      7253151 ----执行KEEP操作之后,通过如下查询出BUFFER_POOL列值为KEEP,表示已经KEEP成功了。 52 SQL> select BUFFER_POOL from user_tables where  TABLE_NAME='JACK';53 54 BUFFER_55 -------56 KEEP57 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;