关于db_file_multiblock_read_count的物理读

我们都知道,数据块是oracle最基本的读写单位,但用户所需要的数据,并不是整个块,而是块中的行,或列.当用户发出SQL语句时,此语句被解析执行完毕,就开始了数据的抓取阶段,在此阶段,服务器进程会先将行所在的数据块从数据文件中读入buffer cache,这个过程叫做物理读.物理读,每读取一个块,就算一次物理读."
我的提问是:
其实就我理解,server process可能会尽可能一次多读一些相关行所属的块到buffer cache中,那么每读一个块都算做一个物理读么?这个不是很理解:)我觉的应该是每次读,并且应该读的数量和一个参数有关系的 db_file_multiblock_read_count,而且也不能说一个block就算做一个物理读。
她的解释是这样的:

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

通过做一个实验,证明了自己先前的理解是问题的,实际上就是如jingjing所说的那样。一个块对应了一个物理读:
来看实验:
SQL> select * from v$version;

BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
PL/SQL Release 9.2.0.8.0 - Production
CORE    9.2.0.8.0       Production
TNS for 32-bit Windows: Version 9.2.0.8.0 - Production
NLSRTL Version 9.2.0.8.0 - Production

SQL> select file_name from dba_data_files;

FILE_NAME
------------------------------------------------------------------------

D:/ORACLE/ORA92/ICMNLSDB/SYSTEM01.DBF
D:/ORACLE/ORA92/ICMNLSDB/UNDOTBS01.DBF
D:/ORACLE/ORA92/ICMNLSDB/INDX01.DBF
D:/ORACLE/ORA92/ICMNLSDB/TOOLS01.DBF
D:/ORACLE/ORA92/ICMNLSDB/USERS01.DBF
D:/ORACLE/ORA92/ICMNLSDB/ASSM.DBF

已选择6行。

SQL> create tablespace mssm
  2  datafile 'D:/ORACLE/ORA92/ICMNLSDB/mssm.dbf' size 10M
  3  extent management local uniform. size 64K
  4  segment space management manual;

表空间已创建。

SQL> create table myallocate
  2  (id int,name char(40)) tablespace mssm;

表已创建。

SQL> select extent_id,block_id,blocks from dba_extents
  2  where wner='SYS' and segment_name='MYALLOCATE';

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

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

为了测试更清晰些,我们在在mssm表空间中建立一个数据段。
SQL> create table mylife
  2  (id int,name char(1000))
  3  storage
  4  (freelists 1 freelist groups 1)
  5  pctfree 50
  6  pctused 50
  7  tablespace mssm;

表已创建。

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

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

根据创建数据段时设置的pctfree可以推算,一个block中可以存储大约三行的数据
SQL> begin
  2  for i in 1 .. 47
  3  loop
  4     insert into mylife values ( i , 'alan');
  5  end loop;
  6  end;
  7  /

PL/SQL
过程已成功完成。

SQL> commit;

提交完成。

SQL> set pagesize 80
SQL> select substr(rowid,1,15) blockID,count(0) from mylife
  2  group by substr(rowid,1,15);

BLOCKID                          COUNT(0)
------------------------------ ----------
AAAGQcAAHAAAAAS                         3
AAAGQcAAHAAAAAT                         3
AAAGQcAAHAAAAAU                         3
AAAGQcAAHAAAAAV                         3
AAAGQcAAHAAAAAW                         3
AAAGQcAAHAAAAAX                         3
AAAGQcAAHAAAAAY                         3
AAAGQcAAHAAAAAZ                         3
AAAGQcAAHAAAAAa                         3
AAAGQcAAHAAAAAb                         3
AAAGQcAAHAAAAAc                         3
AAAGQcAAHAAAAAd                         3
AAAGQcAAHAAAAAe                         3
AAAGQcAAHAAAAAf                         3
AAAGQcAAHAAAAAg                         3
AAAGQcAAHAAAAAh                         2

已选择16行。

SQL> analyze table mylife compute statistics;

表已分析。

SQL> select num_rows,blocks,empty_blocks,num_freelist_blocks
  2  from dba_tables where wner='SYS' and table_name='MYLIFE';

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

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

SQL> select file_id,extent_id,block_id,blocks from dba_extents
  2  where wner='SYS' and segment_name='MYLIFE';

   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';

会话已更改。


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

会话已更改。

SQL> select id,substr(name,1,3) from mylife;
..........
..........

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

会话已更改。

最后我们查看一下跟踪的内容:
select id,substr(name,1,3)
from
 mylife


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.00       0.00          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        5      0.04       0.03         21         27          0          47
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        7      0.04       0.04        21         27          0          47

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: SYS

Rows     Row Source Operation
-------  ---------------------------------------------------
     47  TABLE ACCESS FULL MYLIFE


这里确实就是21次物理读

 

posted @ 2009-12-01 17:50  饺子吃遍天  阅读(125)  评论(0编辑  收藏  举报