2017.04.19的实验探究,这里补上
前言:
对于该参数首次遇到的地方是关于证明"一个查询执行后、抓取记录时,抓取到哪条记录,才会去读相应的块。Oracle并不预先读取所有的块,构造一个结果集,然后从结果集中返回所查询的记录"的时候,该参数造成了一定的影响。有时间再将该实验整理。
拓展来源 http://www.itpub.net/thread-950711-1-1.html
这里研究一下db_file_multiblock_read_count的作用。
网上的资料:
Oracle在读取数据时一次读取的最大block的数量。
理论上,最大db_file_multiblock_read_count和系统IO能力应该有如下关系:
max(db_file_multiblock_read_count) = MaxOsIOsize/db_block_size
当然这个max(db_file_multiblock_read_count)还要受Oracle的限制,
目前Oracle所支持的最大db_file_multiblock_read_count 值为128.
Oracle 初始化参数 DB_FILE_MULTIBLOCK_READ_COUNT (MBRC) 默认值一般是比较低的,在进行一些比较大的数据操作的时候,恰当的调整当前 Session 的 MBRC 的值可能会在 IO 上节省一点时间。(这里抛出一个问题,数据泵之类的工具导出数据时怎么设置session层面的参数)。
DB_FILE_MULTIBLOCK_READ 这个参数的值并不是可以无限大, 大多数平台下的 Oracle 都是 128。一般 Oracle 的 Block Size 是 8K 。128*8K=1M 。 这个 1M 是大多数操作系统一次最大 I/O 的限制。前面的限制要从这个 1M 推回去,初始化参数 DB_FILE_MULTIBLOCK_READ_COUNT 的最大值之所以定为 128 ,也是一个比较保守的策略。
操作系统环境:
- [oracle@oracle ~]$ uname -a
- Linux oracle.example.com 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux
- [oracle@oracle ~]$ lsb_release -a
- LSB Version: :base-4.0-amd64:base-4.0-noarch:core-4.0-amd64:core-4.0-noarch:graphics-4.0-amd64:graphics-4.0-noarch:printing-4.0-amd64:printing-4.0-noarch
- Distributor ID: RedHatEnterpriseServer
- Description: Red Hat Enterprise Linux Server release 6.5 (Santiago)
- Release: 6.5
- Codename: Santiago
数据库版本:
- SYS@proc> select * from v$version where rownum<=1;
-
- BANNER
- --------------------------------------------------------------------------------
- Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
构造测试数据:
- SYS@proc> drop table t purge;
-
- Table dropped.
-
- SYS@proc> create table t as select * from dba_objects where rownum<=1200;
-
- Table created.
-
- SYS@proc> alter table t move tablespace test;
-
- Table altered.
-
- SYS@proc> select dbms_rowid.rowid_block_number(rowid) block#,min(rownum),max(rownum) from t group by dbms_rowid.rowid_block_number(rowid) order by dbms_rowid.rowid_block_number(rowid);
-
- BLOCK# MIN(ROWNUM) MAX(ROWNUM)
- ---------- ----------- -----------
- 171 1 88
- 172 89 171
- 173 172 251
- 174 252 329
- 175 330 407
- 176 408 487
- 177 488 567
- 178 568 646
- 179 647 724
- 180 725 798
- 181 799 873
-
- BLOCK# MIN(ROWNUM) MAX(ROWNUM)
- ---------- ----------- -----------
- 182 874 946
- 183 947 1022
- 185 1023 1104
- 186 1105 1179
- 187 1180 1200
-
- 16 rows selected.
-
- SYS@proc> select EXTENT_ID,FILE_ID,BLOCK_ID,BLOCKS from dba_extents where owner='SYS' and SEGMENT_NAME='T';
-
- EXTENT_ID FILE_ID BLOCK_ID BLOCKS
- ---------- ---------- ---------- ----------
- 0 6 168 8 --168 169 170 171 172 173 174 175
- 1 6 176 8 --176 177 178 179 180 181 182 183
- 2 6 184 8 --184 185 186 187 188 189 190 191
实验过程:
- SYS@proc> show parameter multibl
-
- NAME TYPE VALUE
- ------------------------------------ ----------- ------------------------------
- db_file_multiblock_read_count integer 128
-
- SYS@proc> alter system set db_file_multiblock_read_count=8;
-
- System altered.
-
- SYS@proc> analyze table t compute statistics; --避免动态采样的影响,详情影响结果见http://blog.itpub.net/30174570/viewspace-2140240/
-
- Table analyzed.
-
- SYS@proc> alter system flush buffer_cache;
-
- System altered.
-
- SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;
-
- no rows selected
-
- SYS@proc> select count(*) from t where rownum<=171;
-
- COUNT(*)
- ----------
- 171
-
- SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;
-
- FILE# DBABLK STATE
- ---------- ---------- ----------
- 6 170 1
- 6 171 1
- 6 172 1
- 6 173 1
- 6 174 1
- 6 175 1
-
- 6 rows selected.
1. select count ( * ) from t where rownum < = 171该语句只读取了t表的前两个块171和172;
2.db_file_multiblock_read_count = 8 表明读取数据时Oracle一次读取的数据块会达到最大8个
3.170块并不包含实际数据,但是应该包含关于T表一些信息,所以每次都会读取。(待探究) 。因为不是读取数据过程,170块不算第一个块。
4.171,172自然不用说。这是读取的第一、二个块。
5.由于db_file_multiblock_read_count影响,接下去应该读取多6个块,跟前边两个块凑足8个。
但是这里却只读了173,174,175三个块。原因见6。
6.实际上描述是“在读取数据时一次读取的最大block的数量”,这里达不到8个是因为另外一个因素,读取多余的块的时候遇到区的尽头就停止读取,受到区范围的影响。
从上边实验数据知道,0号区的块是168 169 170 171 172 173 174 175,刚好175是0号区最后一个块,所以此次只读了6个块。从10046结果看:
- WAIT #139854147886688: nam='Disk file operations I/O' ela= 454 FileOperation=2 fileno=6 filetype=2 obj#=89310 tim=1482082121461330
- WAIT #139854147886688: nam='db file sequential read' ela= 21 file#=6 block#=170 blocks=1 obj#=89310 tim=1482082121461405
- WAIT #139854147886688: nam='db file scattered read' ela= 41 file#=6 block#=171 blocks=5 obj#=89310 tim=1482082121461586
oracle分两次io读取,第一次获取必要信息,第二次才是获取数据时的io,受到区范围的影响,第二次io读取了5个块。
网友到这里若是看得懂,那么将db_file_multiblock_read_count设置为4,结果应该读取哪几个块。
我们先分析在验证:
170 171 172 173 174
应该读取上述5个块。
验证过程:
- SYS@proc> alter system set db_file_multiblock_read_count=4;
-
- System altered.
-
- SYS@proc> alter system flush buffer_cache;
-
- System altered.
-
- SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;
-
- no rows selected
-
- SYS@proc> select count(*) from t where rownum<=171;
-
- COUNT(*)
- ----------
- 171
-
- SYS@proc> select file#,dbablk,state from x$bh where obj=(select data_object_id from dba_objects where owner='SYS' and object_name='T') and state<>0 order by dbablk;
-
- FILE# DBABLK STATE
- ---------- ---------- ----------
- 6 170 1
- 6 171 1
- 6 172 1
- 6 173 1
- 6 174 1
遗留或拓展问题:
1.数据泵之类的工具导出数据时怎么设置session层面的参数。
2.上述实验过程分析中的第3点,每次读取多余的不包含数据的块,技术原理以及细节,已解决,详情见http://blog.itpub.net/30174570/viewspace-2140813/。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30174570/viewspace-2140241/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30174570/viewspace-2140241/