原文地址:http://**/viewthread.php?tid=156147
讨论一下DB_FILE_MULTIBLOCK_READ_COUNT参数和区间尺寸的设置问题
作者: Lunar
我们知道Oracle通过两种方式从表中获取数据:
· 通过ROWID(通常使用索引扫描时)
· 通过全表扫描
如果通过ROWID读取数据,表中的区间数就不是读性能的一个因素(如果使用并行查询,那么一个表中有较多的区间的数量可以明显提高I/O的性能),Oracle将通过ROWID直接找到需要的行,并获取相应数据。
如果是全表扫描,那么区间的尺寸大小就有可能导致性能问题。因为全表扫描时,Oracle会一次读取多个Blocks。每次读取的块数将受初始化参数DB_FILE_MULTIBLOCK_READ_COUNT和操作系统的I/O缓冲区大小的限制。比如说,如果Oracle Block的大小是4KB,操作系统I/O缓冲区大小是64KB,那么在全表扫描时每次最多可以读取16各块(Oracle Blocks),所以此时将DB_FILE_MULTIBLOCK_READ_COUNT的值设置为超过16也改变不了全表扫描的性能了。
通常,设置DB_FILE_MULTIBLOCK_READ_COUNT参数是如下考虑的:
(1) 使用一个单独的数据文件创建一个新的表空间
(2) 在该表空间中创建一个单独的未索引的表
(3) 查询V$FILESTAT以验证该测试的初始统计值
(4) 在表上执行全表扫描
(5) 查询V$FILESTAT以确定该测试的终止统计值,并从中减去开始统计值。将PhyBlkRds值除以PhyRds以确定有效的多块读计数。
(6) 删除这个用于测试的表空间
C:>sqlplus "/as sysdba"
SQL*Plus: Release 9.2.0.1.0 - Production on 星期六 6月 28 10:11:22 2003
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
已连接到空闲例程。
SQL> startup
ORACLE 例程已经启动。
Total System Global Area 93395628 bytes
Fixed Size 453292 bytes
Variable Size 67108864 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
数据库装载完毕。
数据库已经打开。
SQL> show parameter db_block_size;
NAME TYPE VALUE
------------------------------------ ----------- ---------------------
db_block_size integer 8192
SQL> show parameter DB_FILE_MULTIBLOCK_READ_COUNT;
NAME TYPE VALUE
------------------------------------ ----------- ----------
db_file_multiblock_read_count integer 16
SQL>
使用一个单独的数据文件创建一个新的表空间:
SQL> create tablespace lunar
2 datafile 'd:lunar.dbf' size 10m
3 default storage(initial 1m next 1m pctincrease 0);
表空间已创建。
在该表空间中创建一个单独的未索引的表:
SQL> create table lunar
2 tablespace lunar
3 as select * from dba_objects;
表已创建。
SQL> select relative_fno from dba_data_files
2 where tablespace_name='LUNAR';
RELATIVE_FNO
------------
15
查询V$FILESTAT以验证该测试的初始统计值:
SQL> select phyrds,phyblkrd from v$filestat
2 where file#=15;
PHYRDS PHYBLKRD
---------- ----------
0 0
在表上执行全表扫描:
SQL> select count(*) from lunar;
COUNT(*)
----------
27547
查询V$FILESTAT以确定该测试的终止统计值:
SQL> select phyrds,phyblkrd from v$filestat
2 where file#=15;
PHYRDS PHYBLKRD
---------- ----------
24 376
SQL>
PHYRDS 和 PHYBLKRD 的初始统计的值都是0;
PHYRDS 和 PHYBLKRD 的终止统计的值分别是24和 376;
PHYRDS 的终止统计的值 - PHYRDS 的初始统计的值 =24;
PHYBLKRD 的终止统计的值 - PHYBLKRD 的初始统计的值 =376;
PHYBLKRD 的差值 / PHYRDS 的差值 = 15.67
所以,有效的多块读计数是16
需要注意的是,如果不是用新的表空间测试,那么测试得到第3步和第5步的差值后,在会话级改变DB_FILE_MULTIBLOCK_READ_COUNT参数,然后再次得到第3步和第5步的差值,并重复测过程。
记住,不要将DB_FILE_MULTIBLOCK_READ_COUNT参数设置的比计算的值高。
设置区间尺寸大小的考虑思路应该是合理的利用Oracle的能力以便在全表扫描时执行多块存取,同时读操作又是不能跨区间的。举个例子,假设操作系统I/O缓冲区大小是64KB,考察读取一个640KB大小的表,如果设置为每个区间64KB,一共10个区间,如果执行全表扫描,则Oracle需要10次读操作(相当于一次读一个区间);如果设置为一个640KB的区间,则Oracle还是需要10次读操作(因为操作系统I/O缓冲区大小是64KB),可见压缩区间并不能提高性能;如果设置为每个区间80KB,一共8个区间,则每个区间Oracle需要读两次,第一次读64KB,第二次读这个区间剩余的16KB(读操作不能跨区间),所以总共需要16次读操作(相当于一次读一个区间)。区间尺寸的设置对性能的影响是显而易见的。
综上,总结起来设置区间大小时需要考虑下面的问题:
· 创建明显大于或者等于操作系统I/O缓冲区大小的区间(最好是操作系统I/O缓冲区大小的整数倍)。这样,如果区间非常大,即使区间大小不是操作系统I/O缓冲区大小的整倍数,也只需要很少的附加读操作(如果上面的640KB和80KB的差异)。
· 设置DB_FILE_MULTIBLOCK_READ_COUNT以充分利用操作系统I/O缓冲区的大小。应考虑DB_FILE_MULTIBLOCK_READ_COUNT <= 操作系统I/O缓冲区 / Oracle Block的大小,如果DB_FILE_MULTIBLOCK_READ_COUNT设置的太大,会使优化器认为全表扫描更有效而改变执行计划,然后实际情况并非如此。
· 如果必须创建小的区间,创建其大小是操作系统I/O缓冲区大小的整数倍
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/18760228/viewspace-716067/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/18760228/viewspace-716067/