关于db_file_multiblock_read_count的研究分析

这期内容当中小编将会给大家带来有关关于db_file_multiblock_read_count的研究分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

  初始化参数db_file_multiblock_read_count 影响Oracle在执行全表扫描时一次读取的block的数量。

  db_file_multiblock_read_count的设置要受OS最大IO能力影响,也就是说,如果你系统的硬件IO能力有限,即使设置再大的db_file_multiblock_read_count也是没有用的。

  理论上,最大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。

  data block是oracle最基本的读写单位,但用户所需要的数据,并不是整个块,而是块中的行或列。当用户发出SQL语句时,此语句被解析执行完毕,就开始了数据的抓取阶段,在此阶段,服务器进程会先将行所在的数据块从数据文件中读入buffer cache,这个过程叫做物理读。每读取一个块,就算一次物理读。

  以我的理解,server process可能会尽可能一次多读一些相关行所属的block到buffer cache中,那么每读一个块都算做一个物理读吗?还是说每读一次(读的block数量和参数db_file_multiblock_read_count有关)就算一个物理读。

  实际上,在使用db_file_multiblock_read_count的时候,一次如果读16个块,在oracle中仍按照16次物理读计算,并不按一次物理读计算。在操作系统级应该按一次I/O请求来计算。

  下面,我们通过一个试验来验证以上情况。

SQL> show parameter db_file_multiblock_read_count

NAME                                 TYPE        VALUE
———————————— ———– ——————————
db_file_multiblock_read_count        integer     16

这个值实际上是一次全表扫描的时要读取的数据块。

SQL> select file_name from dba_data_files;

FILE_NAME
——————————————————————————–
/oracle/database/orcl/users01.dbf
/oracle/database/orcl/sysaux01.dbf
/oracle/database/orcl/undotbs01.dbf
/oracle/database/orcl/system01.dbf
/oracle/database/orcl/DAT_DB
/oracle/database/orcl/xb_db

6 rows selected

SQL> create tablespace test
  2   datafile '/oracle/database/orcl/testdb.dbf' size 10M
  3   extent management local uniform. size 64K
  4   segment space management manual;

Tablespace created

SQL> create table first_table(id int,name varchar(40)) tablespace test;

Table created

为了测试需要,创建了一个新的表空间,并新增了一个数据表,查看表空间中该table的block分配情况如下:

SQL> select extent_id, block_id, blocks
  2    from dba_extents
  3   where wner = 'MS'
  4     and segment_name = upper('first_table');

 EXTENT_ID   BLOCK_ID     BLOCKS
———- ———- ———-
         0          9          8

由于这个数据段是test表空间的第一个初始段,可以看到extent 0的第一个block是从9#开始,1-2#用于数据文件头,3-8#就是位图管理的信息,这里就不多介绍了。

为了进一步测试物理读的问题,通过举例数据表的读取来验证一下。

SQL> create table data_table(id int,name char(1000))
  2   storage(freelists 1 freelist groups 1)
  3   pctfree 50
  4   pctused 50
  5   tablespace test;

Table created

SQL> show parameter db_block_size;

NAME                                 TYPE        VALUE
———————————— ———– ——————————
db_block_size                        integer     8192

根据创建数据段时设置的pctfree 50可以推算,一个block中可以存储大约三行的数据。

下面,插入测试数据。

SQL> begin
  2    for i in 1 .. 47 loop
  3      insert into data_table values (i, 'just test data block allocate');
  4    end loop;
  5  end;
  6  /

PL/SQL procedure successfully completed

SQL> commit;

Commit complete

SQL>
SQL> select substr(rowid, 1, 15) blockID, count(0)
  2    from data_table
  3   group by substr(rowid, 1, 15);

BLOCKID                          COUNT(0)
—————————— ———-
AAAuRMAAHAAAAAV                         3
AAAuRMAAHAAAAAZ                         3
AAAuRMAAHAAAAAX                         3
AAAuRMAAHAAAAAh                         2
AAAuRMAAHAAAAAS                         3
AAAuRMAAHAAAAAd                         3
AAAuRMAAHAAAAAb                         3
AAAuRMAAHAAAAAW                         3
AAAuRMAAHAAAAAf                         3
AAAuRMAAHAAAAAc                         3
AAAuRMAAHAAAAAT                         3
AAAuRMAAHAAAAAU                         3
AAAuRMAAHAAAAAY                         3
AAAuRMAAHAAAAAa                         3
AAAuRMAAHAAAAAe                         3
AAAuRMAAHAAAAAg                         3

16 rows selected

SQL> analyze table data_table compute statistics;

Table analyzed

SQL>
SQL> select num_rows, blocks, empty_blocks, num_freelist_blocks
  2    from dba_tables
  3   where wner = 'MS'
  4     and table_name = upper('data_table');

  NUM_ROWS     BLOCKS EMPTY_BLOCKS NUM_FREELIST_BLOCKS
———- ———- ———— ——————-
        47         20            3                   5

可以看到数据段在HWM下共占有21个数据块,这里显示20是因为有一个块是段头,20个block中有5个block在freelist上面。

SQL> select file_id, extent_id, block_id, blocks
  2    from dba_extents
  3   where wner = 'MS'
  4     and segment_name = upper('data_table');

   FILE_ID  EXTENT_ID   BLOCK_ID     BLOCKS
———- ———- ———- ———-
         7          0         17          8
         7          1         25          8
         7          2         33          8

SQL> alter session set events 'immediate trace name flush_cache';

Session altered

SQL> alter session set events '10046 trace name context forever,level 14' ;

Session altered

SQL> select id, name from data_table;

。。。

47 rows selected

SQL> alter session set events '10046 trace name context off';

Session altered

通过session级别的trace event 10046,得到SQL执行一次产生了21次物理读。

 

Published by

风君子

独自遨游何稽首 揭天掀地慰生平

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注