buffer cache的设置随着Oracle版本的升级而不断变化。Oracle 8i下使用db_block_buffers来设置,该参数表示buffer cache中所能够包含的内存数据块的个数;Oracle 9i以后使用db_cache_size来设置,该参数表示buffer cache的总共的容量,可以用字节、KB、MB为单位来进行设置。而到了Oracle 10g以后则更加简单,甚至可以不用去单独设置buffer cache的大小。因为Oracle 10g引入了ASMM(Automatic Shared Memory Management)这样一个可以进行自我调整的组件,该组件可以自动调整shared pool size、db cache size等SGA中的组件。只需要设置sga_target参数,再设置statistics_level为typical或all,则其他组件就能够根据系统的负载和历史信息自动地调整各个部分的大小。

 

从Oracle 8.0以后,Oracle提供了三种类型的buffer cache,分别是default、keep、recycle。keep和recycle是可选的,default必须存在。Oracle 8i以后使用db_cache_size设置default池、db_keep_cache_size设置keep池、db_recycle_cache_size设置recycle池。

 

通常将经常访问的对象放入keep类型的buffer cache里,而将不常访问的大表放入recycle类型的buffer cache里。其他没有指定buffer cache类型的对象都将进入default类型的buffer cache里。为对象指定buffer cache类型的方法如下:

SQL> create table test (n number) storage (buffer_pool keep);

SQL> alter table test storage (buffer_pool recycle);

 

如果没有指定buffer_pool短语,则表示该对象进入default类型的buffer cache。

这里要说明的是,从名字上看,很容易让人误以为这三种buffer cache提供了三种不同的管理内存数据块的机制。但事实上,它们之间在管理和内部机制上没有任何的区别。它们仅仅是为DBA们提供了一个选择,就是能够将数据库对象分成“非常热的”、“比较热的”和“不热的”这三种类型。因为数据库中总会存在一些“非常热”的对象,它们频繁地被访问。而如果某个时候系统偶尔做了一次大表的全表扫描,就有可能将这些对象清除出内存。为了防止这种情况的发生,我们可以设置keep类型的buffer cache,并将这种非常热的对象都移入keep buffer cache中。同样的,数据库中也总会有一些很大的表,可能每月为了生成一张报表,而只需要访问一次就可以了。但有可能就是这么一次访问,就将大部分的内存数据块清除出了buffer cache。为了避免这种情况的发生,可以设置recycle类型的buffer cache,并将这种偶尔访问的大表移入recycle buffer cache。

 

毫无疑问,如果我们要设置这三种类型的buffer cache,则需要自己研究并根据数据库中的对象进行分类,计算这些对象的大小以后,从而才能够正确的把它们放入不同的buffer cache。但是,不管怎么说,设置这三种类型的buffer cache只能算是最低层次的优化,也就是说在我们没有任何办法的情况下,可以考虑设置它们。但是如果我们能够对某条读取了过多数据块的SQL语句进行调优的话,使其buffer gets降低50%的话,就会比设置多个buffer cache要好得多了。

 

Oracle 9i以后还提供了可以设置多种数据块尺寸(2、4、8、16 或 32)的buffer cache,以便存放不同数据块尺寸的表空间中的对象。使用初始化参数db_Nk_cache_size来指定不同数据块尺寸的buffer cache,这里的N就是2、4、8、16 或 32。创建数据库时,使用初始化参数db_block_size所指定默认的标准数据块尺寸,标准数据块尺寸用于system表空间。然后可以指定最多4个不同的、非标准数据块尺寸的表空间。每种数据块尺寸的表空间必须对应一种不同尺寸的buffer cache,否则不能创建不同数据块尺寸的表空间。

 

SQL> create tablespace tbs_test_16k

2  datafile 'C:\oracle\oradata\ora92\tbs_test_16k.dbf' size 10M

3  blocksize 16k;

create tablespace tbs_test_16k

*

ERROR 位于第 1 行:

ORA-29339: 表空间块大小 16384 与配置的块大小不匹配

SQL> show parameter db_16k_cache_size

NAME                    TYPE      VALUE

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

db_16k_cache_size         big integer   0

 

我们可以看到,由于没有指定16k数据块所对应的buffer cache,所以创建16k数据块的表空间会失败。我们先设置db_16k_cache_size,然后再试着创建16k数据块的表空间。

SQL> alter system set db_16k_cache_size=10M;

系统已更改。

SQL> create tablespace tbs_test_16k

2  datafile 'C:\oracle\oradata\ora92\tbs_test_16k.dbf' size 10M

3  blocksize 16k;

表空间已创建。

 

不同尺寸数据块的buffer cache的管理和内部机制与默认数据块的buffer cache没有任何的分别。它最大的好处是,当使用可传输的表空间从其他数据库中将不同于当前默认数据块尺寸的表空间传输过来的时候,可以不做很多的处理直接导入到当前数据库,只需要设置对应数据块尺寸的buffer cache即可。同时,多种数据块大小的表空间对于调优OLTP和OLAP混合的数据库也有一定的好处。OLTP环境下,倾向于使用较小的数据块,而OLAP环境下,由于基本都是执行全表扫描,因此倾向于使用较大的数据块。这时,可以将OLAP的表转移到使用大数据块(比如32KB)的表空间里去。而将OLTP的表放在中等大小的数据块(比如8KB)的表空间里。

 

要注意的是,keep池和recycle池只能使用标准块大小。

 

在如何设置buffer cache的大小上,从Oracle 9i开始通过初始化参数db_cache_advice,从而启动buffer cache顾问,该顾问提供了可以参考的建议值。Oracle会监控default类型、keep类型和recycle类型的buffer cache的使用,以及其他五种不同数据库尺寸(2、4、8、16 或 32KB)的buffer cache的使用。在典型负荷的时候,启用该参数,从而收集数据帮助用户确定最佳的db_cache_size的大小。该参数有以下三个值。

  off:不收集数据。

  on:开始分配内存收集数据,会造成CPU和内存的负担,可能引起4031错。

  ready:不收集数据,但是收集数据的内存已经预先分配好了。通过把该参数值从off设置为ready,然后再设置为on,就可以避免出现4031错。

 

Oracle会根据当前所监控到的物理读的速率,从而估算出在不同大小尺寸的buffer cache下,所产生的可能的物理读的数量。Oracle会将这些收集到的信息放入视图v$db_cache_advice中。每种类型的buffer cache都会有相应的若干条记录来表示所建议的buffer cache的大小。比如下面,我们显示对于默认类型的、默认数据块尺寸的buffer cache的建议大小应该是多少。

SQL> SELECT size_for_estimate, buffers_for_estimate,

2         estd_physical_read_factor,estd_physical_reads

3  FROM v$db_cache_advice

4  WHERE NAME = 'DEFAULT'

5  AND block_size = (SELECT   VALUE

6  FROM v$parameter

7  WHERE NAME = 'db_block_size')

8  /

SIZE_FOR_ESTIMATE BUFFERS_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR

ESTD_ PHYSICAL_READS

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

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

  4                 500                    1.3869           40154

  8                1000                  1.3848             40093

  12                1500                   1.1861           34339

…….

  32              4000                  1                   28952

  36                4500                 0.8671             25104

  40               5000                 0.8671              25104

  44              5500                  0.8671              25104

  48               6000                   0.7422            21488

  52              6500                  0.7422              21488

  56               7000                  0.7422             21488

  60               7500                   0.554             16040

  64               8000                   0.554             16040

……

  80              10000                0.554                16040

02:33:42 SQL> r

1  select SIZE_FOR_ESTIMATE ,BUFFERS_FOR_ESTIMATE,ESTD_PHYSICAL_READ_FACTOR,ESTD_PHYSICAL_READS

2  from v$db_cache_advice

3    where name='DEFAULT'

4  AND block_size=(

5*                     select value from v$parameter where name='db_block_size')

SIZE_FOR_ESTIMATE BUFFERS_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS

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

16                 1996                     1.042                4112

32                 3992                         1                3946

48                 5988                         1                3946

64                 7984                         1                3946

80                 9980                         1                3946

96                11976                         1                3946

112                13972                         1                3946

128                15968                         1                3946

144                17964                         1                3946

160                19960                         1                3946

176                21956                         1                3946

192                23952                         1                3946

208                25948                         1                3946

224                27944                         1                3946

240                29940                         1                3946

256                31936                         1                3946

272                33932                         1                3946

SIZE_FOR_ESTIMATE BUFFERS_FOR_ESTIMATE ESTD_PHYSICAL_READ_FACTOR ESTD_PHYSICAL_READS

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

288                35928                         1                3946

304                37924                         1                3946

320                39920                         1                3946

20 rows selected.

 

这里的字段estd_physical_read_factor表示在相应buffer cache的尺寸(由字段size_for_estimate表示)下,估计从硬盘里读取数据的次数除以在内存里发生的逻辑读的总次数。如果在内存里的逻辑读没有引起物理读,则该比值为空。在内存足够的前提下,这个比值应该是越低越好的。从该输出可以看到,当前buffer cache为32MB。如果buffer cache为12MB,而不是当前的32MB,则估计产生的物理读会是当前buffer cache尺寸下的1.1861倍,也就是增加了18.6%左右的物理读(1.1861-1)。而如果增加buffer cache,将其设置为60MB,会使得物理读减少45%左右(1-0.554)。而如果继续增加buffer cache,会看到物理读不再会减少。也就是说,如果我们有足够的物理内存,则只需要将buffer cache设置为60MB即可。因为再继续增加buffer cache,也不会带来更多的好处。