最近在尝试优化一个包含blob字段表的查询,考虑使用非标准块缓存。但是,在尝试设置DB_32K_CACHE_SIZE参数时,遭遇报错(报错内容:ORA-00382: 32768 不是有效的块大小, 有效范围为 [..])。于是,到官方文档查了一下,才明白这个参数的设置由于和底层数据块相关,与操作系统是紧密相连的。在Windows操作系统下,DB_32K_CACHE_SIZE参数时不可用的,但是,它支持DB_16K_CACHE_SIZE。
这里给出参数的官方文档说明以及具体的操作过程,仅供参考。
官方文档说明DB_nK_CACHE_SIZE
属性
描述
参数类型
整型数
语法
DB_[2 | 4 | 8 | 16 | 32]K_CACHE_SIZE =integer[K | M | G]
默认值
0 (默认情况下,不设置非标准块大小缓存)
修改
ALTER SYSTEM
取值范围
最小值: 0 (如果值大于0,会自动修改为内存颗粒大小*处理器个数,或者4MB*CPU个数,取二者较大值)
最大值: 取决于操作系统
基本参数
否
DB_nK_CACHE_SIZE (其中 n = 2, 4, 8, 16, 32) 指定了nK缓存区的大小。你可以设置除DB_BLOCK_SIZE之外的其他数值。例如,如果DB_BLOCK_SIZE为4096,那么你设置DB_4K_CACHE_SIZE就是非法的(因为4K的缓存区大小已经被DB_CACHE_SIZE参数设置过了)。
如果数据库中存在nK块大小的在线表空间,那么不能设置该参数为0。
操作系统会限制特定的块大小。例如,如果操作系统最大块尺寸小于32KB,那么你不能设置DB_32K_CACHE_SIZE参数。同样,如果最小块尺寸大于2KB,那么你也不能设置DB_2K_CACHE_SIZE参数。
操作环境
我在Oracle10g+Windows Server 2008 Standard R2环境下进行以下操作。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition 10.2.0.4.0 - 64bi
PL/SQL 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for 64-bit Windows: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - Production
SQL>
查看DB_BLOCK_SIZE
首先,我们查看一下数据库的标准块大小,这个是由DB_BLOCK_SIZE参数决定的。
SQL>
SQL> parameter db_block_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192
SQL>
根据官方文档的解释,这就意味着我们是无法设置DB_8K_CACHE_SIZE参数的,否则会报错,如下所示:
SQL>
SQL> alter system set db_8k_cache_size=200M;
alter system set db_8k_cache_size=200M
*
第 1 行出现错误:
ORA-32017: 更新 SPFILE 时失败
ORA-00380: 无法指定 db_8k_cache_size, 因为 8K 是标准块大小
SQL>
查看所有与cache size相关的参数
根据官方文档的说明,默认情况下DB_nK_CACHE_SIZE参数的值都是0,我们可以查看一下所有与cache size相关的参数。
SQL> parameter cache_size
NAME TYPE VALUE
------------------------------------ ----------- ------------------------
db_16k_cache_size big integer 0
db_2k_cache_size big integer 0
db_32k_cache_size big integer 0
db_4k_cache_size big integer 0
db_8k_cache_size big integer 0
db_cache_size big integer 0
db_keep_cache_size big integer 0
db_recycle_cache_size big integer 0
SQL>
设置DB_32K_CACHE_SIZE报错
我尝试把DB_32K_CACHE_SIZE参数修改为200M,遭遇报错。
SQL> alter system set db_32k_cache_size=200M;
alter system set db_32k_cache_size=200M
*
第 1 行出现错误:
ORA-32017: 更新 SPFILE 时失败
ORA-00382: 32768 不是有效的块大小, 有效范围为 [..]
现在明白了,这个参数的设置和操作系统紧密相关。既然无法设置DB_32K_CACHE_SIZE,也就是说,Windows Server 2008 Standard R2操作系统的最大块尺寸是小于32K的。
设置DB_16K_CACHE_SIZE
那么,接下来我们尝试设置DB_16K_CACHE_SIZE参数。
SQL>
SQL> alter system set db_16k_cache_size=200M;
系统已更改。
SQL> parameter db_16k
NAME TYPE VALUE
------------------------------------ ----------- -----------------------
db_16k_cache_size big integer 208M
SQL>
从结果来看我们是设置成功了,但是我们明明设置的是200M,为什么查出来的是208M呢?这个我们也可以从官方文档的说明中找到答案——“如果值大于0,会自动修改为内存颗粒大小*处理器个数,或者4MB*CPU个数,取二者较大值”。我看了一下系统的硬件配置,双核*12CPU,也就是有24个CPU。那么,内存颗粒大小即granule又是什么呢?
原来,SGA中的各个组件分配都是以granule作为一个单位来分配的,而并不是一次分配1M或1K这样的单位。granule大小是以SGA大小由系统设定的,当SGA小于1G时,granule大小为4M,当SGA大于1G的时候granule大小为16M。接下来,我们查看一下sga以及granule大小。
SQL> sga
Total System Global Area 1258291200 bytes
Fixed Size 2163712 bytes
Size 360446976 bytes
Database Buffers 889192448 bytes
Redo Buffers 6488064 bytes
SQL>
SQL> select component,granule_size from v$sga_dynamic_components;
COMPONENT GRANULE_SIZE
---------------------------------------------------------------- ------------
shared pool 16777216
large pool 16777216
java pool 16777216
streams pool 16777216
DEFAULT buffer cache 16777216
KEEP buffer cache 16777216
RECYCLE buffer cache 16777216
DEFAULT 2K buffer cache 16777216
DEFAULT 4K buffer cache 16777216
DEFAULT 8K buffer cache 16777216
DEFAULT 16K buffer cache 16777216
DEFAULT 32K buffer cache 16777216
ASM Buffer Cache 16777216
已选择13行。
SQL>
由此,我们知道granule大小为16M。但是208,granule大小*处理器个数,或者4MB*CPU个数,这几个数字始终联系不到一起。
于是,我又尝试把db_16k_cache_size设为100M,看看是什么效果。
SQL>
SQL> alter system set db_16k_cache_size=100M;
系统已更改。
SQL> parameter db_16k
NAME TYPE VALUE
------------------------------------ ----------- ------------------------
db_16k_cache_size big integer 112M
SQL>
我们设置的110M,查询结果是112M,还是找不出规律,这个问题放到以后再研究一下。
: