天天看点

Buffer Cache

buffer cache:default pool & keep pool & recycle 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用于存储临时使用的、不被经常使用的较大的对象,这些对象放置在default buffer pool显然是不合适的,这些块会导致过量的缓冲区刷新输出,而且不会带来任何好处,因为等你想要再用这个块时,它可已经老化退出了缓存。要把这些段与默认池和保持池中的段分开,这样就不会导致默认池和保持池中的块老化而退出缓存。

--表缓存   

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 个缓存,要确定它们的大小,还要为这些缓存分配对象。还要记住,这些池之间没有共享,所以,如果保持池有大量未用的空间,即使默认池或回收池空间不够用了, 保持池也不会把未用空间交出来。总之,这些池一般被视为一种非常精细的低级调优设备,只有所有其他调优手段大多用过之后才应考虑使用。

#####################################################################

multiple buffer pools let you address these differences. you can use a keep buffer pool to maintain frequently accessed segments in the buffer cache, and a recycle buffer pool to prevent objects from consuming unnecessary space in the cache. when an object is associated with a cache, all blocks from that object are placed in that cache. oracle maintains a default buffer pool for objects that have not been assigned to a specific buffer pool. the default buffer pool is of size db_cache_size. each buffer pool uses the same lru replacement policy (for example, if the keep pool is not large enough to store all of the segments allocated to it, then the oldest blocks age out of the cache).

我同事认为:buffer pool和keep pool 都使用了lru算法,oracle就是给分了两个池,取了不同的名字而已;里面机制都是一样的;

而我认为:虽然buffer pool和keep pool 都使用了lru算法,但是应该存在如下的区别:

          假设一个sql走了一个索引a,a索引有100个数据块,其中该sql访问了5个数据块;如果该索引使用了buffer pool,该sql将会导致5个数据块读入buffer pool,而如果该索引使用了keep pool,那100个块都将读入keep pool;请大家一块来讨论一下。。

好像我错了 :

只缓存了数据读取的数据,而不是整个索引去读取;

create table t_keep as select * from dba_source;

create index ind_t_name on t_keep (name) storage (buffer_pool keep);

alter table t_keep storage (buffer_pool keep);

sql> select sum(blocks) from user_extents where segment_name = 't_keep';

sum(blocks)

-----------

       5760

sql> select object_name, a.status, count(*)

  2   from v$bh a, user_objects b

  3   where a.objd = b.object_id

  4   and object_name in ('t_keep')

  5   group by object_name, a.status;

object_name                    status    count(*)

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

t_keep                         xcur            98

sql> select sum(blocks) from user_extents where segment_name = 'ind_t_name';

        768

  2       from v$bh a, user_objects b

  3       where a.objd = b.object_id

  4       and object_name in ('ind_t_name')

  5       group by object_name, a.status;

ind_t_name                     xcur            21

set autot on stat

sql> select count(1) from t_keep where name='prpjplanfeelock';

  count(1)

----------

        51

statistics

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

         63  recursive calls

          0  db block gets

         82  consistent gets

         16  physical reads

          0  redo size

        515  bytes sent via sql*net to client

        492  bytes received via sql*net from client

          2  sql*net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

  2           from v$bh a, user_objects b

  3           where a.objd = b.object_id

  4           and object_name in ('ind_t_name')

  5           group by object_name, a.status;

ind_t_name                     xcur            37

读取前缓存里有21个数据块,执行sql使用了16个物理读,执行sql后缓存中只有37(21+16)个,说明只缓存了读取的数据块;

继续阅读