ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 谈谈Buffer Cache中Keep和Recycle子池(中)

谈谈Buffer Cache中Keep和Recycle子池(中)

原创 Linux操作系统 作者:realkid4 时间:2012-01-12 00:19:00 0 删除 编辑

 

上篇中我们分析了buffer cache的原理和子池划分。本篇来探讨keep池的使用细节。

 

5、子池对象定义和特性——Keep池

 

Keep池的使用有一些设置的因素。

 

 

SQL> alter system set db_keep_cache_size=10M;

System altered

 

SQL> select component, current_size, min_size, max_size from v$sga_dynamic_components where component in ('DEFAULT buffer cache','KEEP buffer cache','RECYCLE buffer cache');

 

COMPONENT                      CURRENT_SIZE   MIN_SIZE   MAX_SIZE

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

DEFAULT buffer cache               62914560   62914560          0

KEEP buffer cache                  12582912          0          0

RECYCLE buffer cache                      0          0          0

 

 

Keep池的定义,首先是从数据表开始。我们首先在scott用户下,设置一个数据表t_keep,使用storage子句定义为KEEP池对象。

 

--注意,此处是scott用户

SQL> show user;

USER 为 "SCOTT"

 

 

SQL> create table t_keep as select * from dba_objects;

Table created

 

SQL> alter table t_keep cache;

Table altered

 

SQL> alter table t_keep storage(buffer_pool keep);

Table altered

 

 

调用命令:

 

(篇幅原因,有省略

--第一次调用

SQL> select count(*) from t_keep;

已用时间:  00: 00: 01.73

 

统计信息

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

        179  recursive calls

          0  db block gets

        715  consistent gets

        699  physical reads

 

SQL> select count(*) from t_keep;

已用时间:  00: 00: 00.01

统计信息

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

          0  recursive calls

          0  db block gets

        698  consistent gets

          0  physical reads

 

 

 

那么,两次调用中,第二次调用执行时间短(0.01s),而且没有发生物理读。缓存的t_keep数据表块是不是放在keep池中了呢?我们在MOS [ID 373472.1]中,找到一个脚本,用来判断对象缓冲池的情况。我们进行适当改写,如下:

 

 

select decode(pd.bp_id,1,'KEEP',2,'RECYCLE',3,'DEFAULT',

              4,'2K SUBCACHE',5,'4K SUBCACHE',6,'8K SUBCACHE',

              7,'16K SUBCACHE',8,'32K SUBCACHE','UNKNOWN') subcache,

       bh.object_name,

       bh.blocks

from   x$kcbwds ds,

       x$kcbwbpd pd,

       (select /*+ use_hash(x) */ set_ds,

               o.name object_name,

               count(*) BLOCKS

        from   obj$ o,

               x$bh x

        where  o.dataobj# = x.obj

        and    x.state !=0 --and o.owner# !=0

        group by set_ds,o.name) bh

where  ds.set_id >= pd.bp_lo_sid

and    ds.set_id <= pd.bp_hi_sid

and    pd.bp_size != 0

and    ds.addr=bh.set_ds

 

 

我们调用该语句,获得结果如下:

 

 

Started spooling to d:\dbbuffer.log

SUBCACHE     OBJECT_NAME                        BLOCKS

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

KEEP         T_KEEP                                694

Stopped spooling to d:\dbbuffer.log

 

 

说明,的确该数据表是缓存在了keep池中。

 

在实验中,笔者发现两个值得关注的细节。首先就是sys用户数据表的缓存情况。下面实验:

 

 

SQL> show user;

User is "SYS"

 

SQL> alter table t cache;

Table altered

 

SQL> alter table t storage(buffer_pool keep);

Table altered

 

 

之后执行语句,将数据块加载到缓存中:

 

 

SQL> select count(*) from t;

已用时间:  00: 00: 01.16

统计信息

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

        124  recursive calls

          0  db block gets

       1399  consistent gets

       1387  physical reads

          0  redo size

 

 

SQL> select count(*) from t;

已用时间:  00: 00: 00.01

统计信息

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

          0  recursive calls

          0  db block gets

       1389  consistent gets

          0  physical reads

        

 

 

但是,调用脚本后,却发现数据表T被缓存在Default池中。

 

 

SQL>

Started spooling to d:\dbbuffer.log

 

SUBCACHE     OBJECT_NAME                        BLOCKS

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

DEFAULT      T                                    1379

Stopped spooling to d:\dbbuffer.log

 

 

说明:对于sys用户的数据表,可以定义缓存keep池。但是实际进行buffer block缓存的时候,只能缓存到Default池内。

 

第二个细节在于,我们定义的keep池大小,通常是有限的。那么,如果数据表超过设置的keep池容量,会有什么影响呢?我们刚刚在scott下建立的数据表,体积大约有6M。但是,我们设置的keep池大小,有12M。

 

 

SQL> col owner for a10;

SQL> col segment_name for a20;

SQL> select owner, segment_name, bytes/1024/1024 from dba_segments where segment_name='T_KEEP';

 

OWNER      SEGMENT_NAME         BYTES/1024/1024

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

SCOTT      T_KEEP                             6

 

SQL> show parameter keep;

NAME                                 TYPE        VALUE

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

buffer_pool_keep                     string     

control_file_record_keep_time        integer     7

db_keep_cache_size                   big integer 12M

 

 

增加t_keep数据表大小,让他超过keep池容量。那么,keep池必然是放不下整个数据表的所有块的。这个时候,Oracle的行为是什么样子呢?我们增加到22M。

 

--增大体积之后

SQL> select owner, segment_name, bytes/1024/1024 from dba_segments where segment_name='T_KEEP';

 

OWNER      SEGMENT_NAME         BYTES/1024/1024

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

SCOTT      T_KEEP                            22

 

 

下面我们调用三次实验语句,观察逻辑IO和物理IO情况。

 

--第一次调用

SQL> select count(*) from t_keep;

已用时间:  00: 00: 01.03

 

统计信息

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

          0  recursive calls

          0  db block gets

       2770  consistent gets

       2766  physical reads

          0  redo size

 

--第二次调用

SQL> select count(*) from t_keep;

已用时间:  00: 00: 01.03

统计信息

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

          0  recursive calls

          0  db block gets

       2770  consistent gets

       2765  physical reads

          0  redo size

--第三次调用

SQL> select count(*) from t_keep;

已用时间:  00: 00: 01.31

 

统计信息

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

          0  recursive calls

          0  db block gets

       2770  consistent gets

       2765  physical reads

   

 

 

 

我们发现,三次调用的执行时间、逻辑物理IO相同。每次都会有一定的物理IO读取。我们观察一下T_KEEP数据表块在内存buffer cache中的情况。

 

 

SQL>

Started spooling to d:\dbbuffer.log

SUBCACHE     OBJECT_NAME                        BLOCKS

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

KEEP         T_KEEP                               1497

Stopped spooling to d:\dbbuffer.log

 

 

发现,始终只有在keep池中的1497个数据块。说明:如果一个数据表不能将所有的数据块放置在设置的keep池中,其他多余的数据块不能缓存在其他池中,而是剔除内存。每次查询的时候进行物理IO操作。

 

经过分析,我们可以获得keep池的使用和约束。通常,如果数据表很小,而且应用高频度访问,没有其他优化空间的情况下,可以考虑将该数据表缓存在keep池中。缓存Keep池的主要作用在于减少物理IO。

 

最后,我们看看recycle的一些特征。

 

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-714776/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
求道~

注册时间:2010-11-30

  • 博文量
    545
  • 访问量
    7569906