参考自盖国强《深入解析oracle》
直接路径读(direct path read)通常发生在 Oracle 直接读数据到进程 PGA 时,这个读取不需要经过 SGA。 这类读取通常在以下情况被使用: 磁盘排序 IO 操作; 并行查询从属进程; 预读操作; 串行全表扫描(Oracle 11g 新特性) 直接路径写(direct path write)通常发生在 Oracle 直接从 PGA 写数据到数据文件或临时文件,这个写操作可以绕过 SGA。 这类写入操作通常在以下情况被使用: 直接路径加载; 并行 DML 操作; 磁盘排序; 对未缓存的“LOB”段的写入,随后会记录为 direct path write (lob)等待。 最为常见的直接路径写,多数因为磁盘排序导致。对于这一写入等待,我们应该找到 I/O操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。 1.磁盘排序诊断 如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑为不同用户分配不同的临时表空间,使用多个临时文件,写入不同磁盘或者裸设备,从而降低竞争,提高性能。对于显著的磁盘排序,可以很容易地猜测到,临时表空间的读写操作肯定相当频繁,可以适当增大 pga_aggregate_target,以缩减磁盘排序对于硬盘的写入,从而提高系统及应用相应。但是通常应该及时检查应用,确认是否因为应用问题而导致了过度排序,从而从根本上解决问题。 2.并行查询性能问题 在很多情况下,并行也许并不是最好的选择,如果表并不大,并行反而会降低其执行速度。 数据库的内存排序率是 100%(In-memory Sort %: 100.00),显然这里的 Direct Path Read 并不是由于排序引发的,注意到另外一个等待事件(KJC: Wait for msg sends to complete)和并行有关,所以初步判断这里的 direct path read 可能和并行有关。 查看涉及数据表的并行度: SQL> select table_name,degree from dba_tables where table_name='WORKER'; TABLE_NAME DEGREE ------------------------------ -------------------- WORKER 1 将表的并行度修改为 1: SQL> alter table test.worker parallel 1; Table altered. 3.磁盘排序与临时文件 direct path read/write temp 就是单指对于临时文件的直接读写操作,为了分离临时文件号和数据文件号,Oracle 对临时文件的编 号以 db_files 为起点,所以临时文件的绝对文件号应该等于 db_files + file#。 4.串行全表扫描 – Serial Table Scan 在 Oracle Database 11g 中,一种被称为 串行全表扫描(Serial Table Scan)的技术被引入,该特性根据数据块的设置和统计信息等,自动决定是采用 Direct Path Read 绕过 SGA,还是采用常规方式读取,因为这种自动选择,这一特性又被称为 自适应直接读(Adaptive Direct Read) . 串行表扫描以物理读方式执行,每次执行该查询,产生同样的物理读. 使用串行全表扫描和多个因素有关,首先全表访问的数据表需要至少超过 5 倍的_small_table_threshold 设置,因为通常小表的全表访问并不会对 Buffer Cache 产生过大的冲击.这个隐含参数的缺省值如下: SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ 2 FROM SYS.x$ksppi x, SYS.x$ksppcv y 3 WHERE x.indx = y.indx AND x.ksppinm LIKE '%&par%'; Enter value for par: _small_table_threshold old 3: WHERE x.indx = y.indx AND x.ksppinm LIKE '%&par%' new 3: WHERE x.indx = y.indx AND x.ksppinm LIKE '%_small_table_threshold%' NAME -------------------------------------------------------------------------------- VALUE -------------------------------------------------------------------------------- DESCRIB -------------------------------------------------------------------------------- _small_table_threshold 1023 lower threshold level of table size for direct reads Oracle支持通过 10949 事件禁用串行全表扫描(但是当表大于 5 倍的 Buffer Cache 时,则不允许禁用,只能采用直接路径读). 10949 事件可以禁用串行表扫描,而另外一个隐含参数_serial_direct_read 则用于启用串行直接路径读. 通过前面的测试可以看到串行表扫描可以提升全表扫描的性能,但是并非总是如此,尤其是当数据可以 Cache 在内存中被反复访问时,无疑 Scattered Read 更有优势,频繁的物理访问对于 IO 密集系统无疑将是灾难,所以这一技术需要在具体环境中根据判断去应用.