我们都知道,数据块是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因为有一个块是段头,20个block中有5个block在freelist上面。
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次物理读