DB_FILE_MULTIBLOCK_READ_COUNT的設置

本文详细介绍了如何通过调整Oracle数据库的DB_FILE_MULTIBLOCK_READ_COUNT参数来优化全表扫描性能,包括如何通过测试计算出最佳的多块读取计数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们知道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步的差值,并重复测过程。

補充,重復第3步和第5步前,注意

alter session set events 'immediate trace name flush_cache'

因為,再次執行會從buffer內讀取,必須清空後,才會有disk io讀取

记住,不要将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缓冲区大小的整倍数,也只需要很少的附加读操作(如果上面的640KB80KB的差异)。

· 设置DB_FILE_MULTIBLOCK_READ_COUNT以充分利用操作系统I/O缓冲区的大小。应考虑DB_FILE_MULTIBLOCK_READ_COUNT <= 操作系统I/O缓冲区 / Oracle Block的大小,如果DB_FILE_MULTIBLOCK_READ_COUNT设置的太大,会使优化器认为全表扫描更有效而改变执行计划,然后实际情况并非如此。

· 如果必须创建小的区间,创建其大小是操作系统I/O缓冲区大小的整数倍

補充:

從另一trace file獲得oracle單次讀取的block數量

alter session set events '10046 trace name context forever,level 12'

select count(*) from lunar;

PARSING IN CURSOR #1 len=68 dep=0 uid=0 oct=42 lid=0 tim=9298786450 hv=1346161232 ad='85354328'

alter session set events '10046 trace name context forever,level 12'

END OF STMT

PARSE #1:c=0,e=272,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=9298786446

BINDS #1:

EXEC #1:c=0,e=64,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=9298786578

WAIT #1: nam='SQL*Net message to client' ela= 2 p1=1413697536 p2=1 p3=0

WAIT #1: nam='SQL*Net message from client' ela= 5998717 p1=1413697536 p2=1 p3=0

=====================

PARSING IN CURSOR #1 len=26 dep=0 uid=0 oct=3 lid=0 tim=9304785606 hv=955040781 ad='853da7c4'

select count(*) from lunar

END OF STMT

PARSE #1:c=0,e=69,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=9304785602

BINDS #1:

EXEC #1:c=0,e=66,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=9304785750

WAIT #1: nam='SQL*Net message to client' ela= 2 p1=1413697536 p2=1 p3=0

WAIT #1: nam='db file sequential read' ela= 11040 p1=8 p2=9 p3=1

WAIT #1: nam='db file scattered read' ela= 12056 p1=8 p2=10 p3=16

WAIT #1: nam='db file scattered read' ela= 2770 p1=8 p2=50 p3=16

WAIT #1: nam='db file scattered read' ela= 2447 p1=8 p2=90 p3=16

WAIT #1: nam='db file scattered read' ela= 912 p1=8 p2=130 p3=7

WAIT #1: nam='db file scattered read' ela= 2414 p1=8 p2=137 p3=16

WAIT #1: nam='db file scattered read' ela= 2452 p1=8 p2=177 p3=16

WAIT #1: nam='db file scattered read' ela= 2711 p1=8 p2=217 p3=16

WAIT #1: nam='db file scattered read' ela= 679 p1=8 p2=257 p3=8

WAIT #1: nam='db file scattered read' ela= 2733 p1=8 p2=265 p3=16

WAIT #1: nam='db file scattered read' ela= 2502 p1=8 p2=305 p3=16

WAIT #1: nam='db file scattered read' ela= 2459 p1=8 p2=345 p3=16

WAIT #1: nam='db file scattered read' ela= 675 p1=8 p2=385 p3=8

WAIT #1: nam='db file scattered read' ela= 2492 p1=8 p2=393 p3=16

注意,上敘的p3=16,記錄了單次ioblock

假如,將db_file_multiblock_read_count改為1000

alter system set db_file_multiblock_read_count=1000;

alter session set events 'immediate trace name flush_cache';

alter session set events '10046 trace name context forever,level 12';

select count(*) from lunar;

再看trace file,如下

PARSING IN CURSOR #1 len=26 dep=0 uid=0 oct=3 lid=0 tim=10603977582 hv=955040781 ad='853da7c4'

select count(*) from lunar

END OF STMT

PARSE #1:c=0,e=60,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=10603977578

BINDS #1:

EXEC #1:c=0,e=62,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=10603977722

WAIT #1: nam='SQL*Net message to client' ela= 1 p1=1413697536 p2=1 p3=0

WAIT #1: nam='db file sequential read' ela= 8290 p1=8 p2=9 p3=1

WAIT #1: nam='db file scattered read' ela= 12303 p1=8 p2=10 p3=127

WAIT #1: nam='db file scattered read' ela= 8081 p1=8 p2=137 p3=128

WAIT #1: nam='db file scattered read' ela= 8401 p1=8 p2=265 p3=128

WAIT #1: nam='db file scattered read' ela= 7918 p1=8 p2=393 p3=128

WAIT #1: nam='db file scattered read' ela= 7877 p1=8 p2=521 p3=128

WAIT #1: nam='db file scattered read' ela= 8118 p1=8 p2=649 p3=128

WAIT #1: nam='db file scattered read' ela= 7649 p1=8 p2=777 p3=128

WAIT #1: nam='db file scattered read' ela= 7492 p1=8 p2=905 p3=128

WAIT #1: nam='db file scattered read' ela= 8053 p1=8 p2=1033 p3=128

WAIT #1: nam='db file scattered read' ela= 4329 p1=8 p2=1161 p3=85

注意P3參數仍為128塊

[@more@]

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

转载于:http://blog.itpub.net/779728/viewspace-1024725/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值