2.1.3. 用户数据文件
由于内存的读写效率比磁盘的读写效率高万倍,因此,为了降低I/O wait,Oracle会将数据cache在内存(Buffer Cache,对Buffer Cache的详细介绍可以参见《Oracle内存全面分析》)中,对数据的读写尽量在内存中完成。当Buffer Cache中的数据缓存块被修改过了,它就被标记为“脏”数据。根据LRU(Least Recently Used)算法,如果一个数据块最近很少被使用,它就称为“冷”数据块。进程DBWn(系统中可以存在多个DBW进程,n为序号)负责将“冷”的“脏”数据写入数据文件中去。DBWn进程会在以下两种情况下将“脏”数据写入磁盘中去: A. 当服务进程扫描一定数量(阀值)的Buffer Cache后还没有找到干净、可重用的缓存块后,它会通知DBWn进程将“脏”数据写入文件中去,以释放出空闲缓存。 B. 当发生检查点(Checkpoint)时。 检查点的作用:
??将数据缓存中所有改变的数据块写入数据文件(不管事物是否提交) ??将数据文件的头部标为一致,并且在控制文件当中记录检查点序号。 ??该检查点号与日志文件中SCN号对应。 ??检查点操作的频繁程度可由数据库参数调节
2.1.4. 临时表空间
当Oracle在执行一些SQL时,会需要一些临时空间来存储执行时产生的中间数据。这些临时空间由Oracle从指定的临时表空间中分配给进程。主要有三种情况会占用临时空间:临时表/索引操作、排序和临时LOB对象操作。 A.临时表/索引: 在会话中,当第一次对临时表进行INSERT(包括CTAS)时,Oracle会从临时表空间中为临时表及其索引分配临时空间一存储数据。 B.排序: 任何会使用到排序的操作,包括JOIN、创建(重建)INDEX、ORDER BY、聚合计算(GROUP BY)以及统计数据收集,都可能使用到临时表空间。排序操作首先会选择在内存中的Sort Area进行(Sort In Memory),一旦Sort Area不足,则会使用临时空间进行排序操作(Sort In Disk)。看下面的例子: SQL> alter session set sort_area_size = 10000000; Session altered. SQL> select owner, object_name from t_test1 order by object_id; 47582 rows selected. Execution Plan Plan hash value: 1312425564 Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | | 0 | SELECT STATEMENT | | 47582 | 1486K| 155 (4)| 00:00:02 | | 1 | SORT ORDER BY | | 47582 | 1486K| 155 (4)| 00:00:02 | | 2 | TABLE ACCESS FULL| T_TEST1 | 47582 | 1486K| 150 (1)| 00:00:02 | Statistics 1 recursive calls 0 db block gets 658 consistent gets Oracle I/O 性能调优手册 第 - 6 - 页,共 - 54 - 页 Welcome to cuishen’s IT Blog: http://cuishen.javaeye.com
0 physical reads 0 redo size 1566184 bytes sent via SQL*Net to client 35277 bytes received via SQL*Net from client 3174 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 47582 rows processed SQL> alter session set sort_area_size = 10000; Session altered. SQL> select owner, object_name from t_test1 order by object_id; 47582 rows selected. Execution Plan Plan hash value: 1312425564 | Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time| | 0 | SELECT STATEMENT | | 47582 | 1486K| | 1251 (1)| 00:00:16 | | 1 | SORT ORDER BY | | 47582 | 1486K| 4136K| 1251 (1)| 00:00:16 | | 2 | TABLE ACCESS FULL| T_TEST1 | 47582 | 1486K| | 150 (1)| 00:00:02 | Statistics 6 recursive calls 20 db block gets 658 consistent gets 629 physical reads 0 redo size 1566184 bytes sent via SQL*Net to client 35277 bytes received via SQL*Net from client 3174 SQL*Net roundtrips to/from client 0 sorts (memory) 1 sorts (disk)
47582 rows processed C.临时LOB对象: LOB对象包括BLOB、CLOB、NCLOB、和BFILE。在PLSQL程序块中,如果定义了LOB变量,则这些LOB变量就是临时LOB对象。临时LOB对象被创建在临时表空间上,直到LOB数据被释放,或者会话结束。
2.1.5. 回滚段
我们知道,一个事务在未被提交前,其做的任何修改都是可以被回滚(Rollback)的。这些回滚数据就被放到回滚段(Rollback Segment)上。此外,一致性读(Read Consistency)、数据库恢复(Recover)都会用到回滚段。 任何数据块的修改都会被记录在回滚段中,甚至Redo Log也会产生回滚记录。当任何一个非只读(只有Oracle I/O 性能调优手册 第 - 7 - 页,共 - 54 - 页 Welcome to cuishen’s IT Blog: http://cuishen.javaeye.com
查询)的事务开始时,oracle会自动为其指定下一个可用的回滚段。事务中任何数据变化都被写入回滚段中。如果事务回滚,Oracle根据回滚段中的回滚记录将buffer cache中的“脏”数据恢复,释放回滚段空间。当事务被提交,由于要保证一致性读,Oracle并不会立即释放回滚段中的数据,而是会保留一段时间。
2.1.6. Archive Log
当Oracle的Archive Log模式被激活后,所有Redo Log数据都会被写入Archive Log文件中以便日后进行恢复。当发生日志组切换时,ARCn(Archive进程,可以存在多个)进程就会将Redo Log文件拷贝到指定存储目录中去,成为Archive Log文件。
2.1.7. Direct-Path Insert
这里,我们还要介绍一种特殊的写操作——Direct-Path Insert(直接路径插入)。Direct-Path Insert通过直接在表中已存在的数据后面添加数据,直接将数据写入数据文件中,而忽略掉了Buffer Cache。 我们前面提到,为了能在意外时恢复数据,每一个数据修改都会被记录到Redo Log中。然而,由于Redo Log需要写入到物理文件中去,是一个比较消耗性能的操作。为了提高性能,我们在批量写入数据时就可以通过Direct-Path Insert的指定NOLOGING的方式来避免写Redo Log。 有多种方法可以指定Direct-Path Insert: A.CTAS(CREATE TABLE AS SELECT) B.SQL*Loader指定Direct参数。 C.在语句中指定APPEND提示。
2.2. 读 2.2.1. 物理读
产生物理读主要有以下几种情况:
第一次读取
当数据块第一次被读取到,Oracle会先将其从磁盘上读入Buffer Cache中,并将他们放在LRU(Last Recently Used)链表的MRU(Most Recently Used)端。再次访问数据块时就可以直接从Buffer Cache中读取、修改了。看以下例子: SQL> select owner, index_name from t_test3; 2856 rows selected. Execution Plan Plan hash value: 2878488296 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 2856 | 68544 | 22 (0)| 00:00:01 | Oracle I/O 性能调优手册 第 - 8 - 页,共 - 54 - 页 Welcome to cuishen’s IT Blog: http://cuishen.javaeye.com
| 1 | TABLE ACCESS FULL| T_TEST3 | 2856 | 68544 | 22 (0)| 00:00:01 | Statistics 407 recursive calls 32 db block gets 344 consistent gets 89 physical reads 0 redo size 103888 bytes sent via SQL*Net to client 2475 bytes received via SQL*Net from client 192 SQL*Net roundtrips to/from client 9 sorts (memory) 0 sorts (disk) 2856 rows processed SQL> select owner, index_name from t_test3; 2856 rows selected. Elapsed: 00:00:00.03 Execution Plan Plan hash value: 2878488296 | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | | 0 | SELECT STATEMENT | | 2856 | 68544 | 22 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| T_TEST3 | 2856 | 68544 | 22 (0)| 00:00:01 | Statistics 0 recursive calls 0 db block gets 276 consistent gets 0 physical reads 0 redo size 103888 bytes sent via SQL*Net to client 2475 bytes received via SQL*Net from client 192 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 2856 rows processed
数据块被重新读入Buffer Cache
如果有新的数据需要被读入Buffer Cache中,而Buffer Cache又没有足够的空闲空间,Oracle就根据LRU算法将LRU链表中LRU端的数据置换出去。当这些数据被再次访问到时,需要重新从磁盘读入。 SQL> select owner, table_name from t_test22 where owner = 'SYS'; 718 rows selected. Oracle I/O 性能调优手册 第 - 9 - 页,共 - 54 - 页 Welcome to cuishen’s IT Blog: http://cuishen.javaeye.com

