direct path read(转)

在Oracle 11g中,全表扫描采用了更高效的直接路径读取方式代替传统的DB FILE SCATTERED READ。这种方式减少了栓的使用,避免了栓争用,并且能够一次性读取更多数据块,提高读取效率。

Oracle 11g版本中串行的全表扫描可能使用直接路径读取(direct path read)的方式取代之前版本中一直使用的DB FILE SCATTERED READ, direct path read具备更多的优势:


1. 减少了对栓的使用,避免可能的栓争用


2.物理IO的大小不再取决于buffer_cache中所存在的块;

试想某个8个块的extent1,3,5,7号块在高速缓存中,而2,4,6,8块没有被缓存,传统的方式在读取该extent时将会是对2,4,6,8块进行4db file sequential read,这是一种十分可怕的状况,其效率往往要比单次读取这个区间的所有8个块还要低得多,虽然Oracle为了避免这种情况总是尽可能的不缓存大表的块(读入后总是放在队列最冷的一端);direct path read则可以完全避免这类问题,尽可能地单次读入更多的物理块。


当然直接路径读取也会引入一些缺点:


1.在直接路径读取某段前需要对该对象进行一次段级的检查点(A segment checkpoint).


2.可能导致重复的延迟块清除操作(我们假设你了解delayed block cleanout是什么).


可以利用10949 事件来避免采用直接路径读取方式

ALTER SESSION SET EVENTS '10949 TRACE NAME CONTEXT FOREVER,level 1';

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24104518/viewspace-715128/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/24104518/viewspace-715128/

<think> 我们首先需要理解Direct Path Read等待事件的含义。根据引用[1]和引用[2]: - Direct Path Read通常发生在Oracle数据库直接从磁盘读取数据到进程的私有内存(PGA)中,而不是先读取到共享内存(SGA)的缓冲区缓存(Buffer Cache)中。 - 这种读取方式常见于全表扫描、全索引扫描等操作,特别是当Oracle认为直接路径读比缓冲区缓存更高效时(例如要读取的数据块非常多,或者表被标记为并行查询等)。 - 引用[2]指出,direct path read temp则主要与临时表空间的使用有关,例如排序操作(如order by、group by、distinct等)或者哈希连接(hash join)时,如果中间结果集太大而无法在PGA中容纳,就会使用临时表空间,从而可能导致direct path read temp等待。 现在,用户的问题是:Direct Path Read在AWR报告等待事件Top10中排第一,需要分析原因和解决方案。 ### 原因分析 1. **大表全表扫描**:当SQL语句执行全表扫描大表时,如果Oracle优化器认为直接路径读更高效,就会使用直接路径读,从而导致该等待事件。特别是当表的大小远大于缓冲区缓存(buffer cache)时,或者表被设置为并行查询时。 2. **排序操作使用临时表空间**:如果SQL语句包含需要排序的操作(如order by、group by、distinct等)或者哈希连接,并且排序区(PGA)不足以容纳中间结果,就会使用临时表空间(磁盘排序),此时会出现direct path read temp(从临时表空间读取)和direct path write temp(写入临时表空间)等待事件。但是注意,用户的问题中等待事件是“Direct path read”,而不是“Direct path read temp”,所以这里主要关注非临时表空间的直接路径读。 3. **并行查询**:并行查询操作(如并行全表扫描)会使用直接路径读,因为每个并行子进程都会独立地从磁盘读取数据到自己的PGA中。 4. **11g及以后版本的自动特性**:从Oracle 11g开始,Oracle引入了自动直接路径读的特性,对于串行全表扫描,当Oracle认为数据块在缓冲区缓存中缓存的比例不高(或者要读取的数据块很多)时,会自动使用直接路径读。这个特性可以通过参数`_serial_direct_read`控制(引用[3]提到可以设置该参数为NEVER来禁用)。 5. **热点块竞争**:虽然引用[2]中提到的buffer busy waits是另一个问题,但需要区分。如果系统同时存在热点块竞争(buffer busy waits),那么直接路径读反而可能是一种缓解方式(因为它绕过了buffer cache)。但是,如果直接路径读过多,也可能导致I/O子系统压力过大。 ### 解决方案 根据上述原因,我们可以提出以下解决方案: 1. **优化SQL语句**: - 避免全表扫描,通过添加合适的索引,将全表扫描变为索引扫描(注意索引扫描通常使用db file sequential read等待事件,但I/O量可能更少)。 - 检查执行计划,确保SQL语句使用了正确的索引。如果已经存在索引但没有使用,考虑收集统计信息或使用提示(hint)引导优化器。 - 减少排序操作:尽量减少使用order by、group by等操作,或者确保这些操作能够在内存(PGA)中完成。可以通过增大`PGA_AGGREGATE_TARGET`参数来减少磁盘排序。 2. **调整缓冲区缓存(Buffer Cache)**: - 如果全表扫描是必要的,并且数据会被频繁访问,那么可以考虑增大缓冲区缓存(`DB_CACHE_SIZE`),使得更多的数据块可以缓存在内存中,从而减少直接路径读。但是,如果表非常大且访问不频繁,使用直接路径读可能更合适,因为不会污染缓冲区缓存。 3. **控制直接路径读行为**: - 如果确认直接路径读导致性能问题(例如I/O子系统无法承受),可以考虑禁用串行直接路径读(针对11g及以上版本)。通过设置以下参数(引用[3]): ```sql ALTER SYSTEM SET "_serial_direct_read" = NEVER; ``` 或者使用事件10949(在11.2.0.2以上版本): ```sql ALTER SYSTEM SET EVENT = '10949 TRACE NAME CONTEXT FOREVER, LEVEL 1' SCOPE=SPFILE; ``` 注意:修改这些参数需要谨慎,因为它们可能会影响优化器的行为,并且可能导致某些操作变慢。 4. **并行查询调整**: - 如果直接路径读主要由并行查询引起,考虑调整并行度(DOP)。过高的并行度会导致大量并行子进程同时进行I/O操作,从而增加I/O子系统压力。可以通过调整表的并行度或者使用`PARALLEL`提示来控制。 5. **硬件和I/O优化**: - 如果I/O子系统是瓶颈,考虑增加磁盘带宽(如使用更快的磁盘,或者增加磁盘数量)、使用ASM条带化(stripe)来分散I/O负载。 6. **检查临时表空间使用**: - 虽然用户的问题主要是direct path read(非temp),但也要注意是否同时存在direct path read temp(临时表空间的直接读取)。如果有,需要优化排序操作(增大PGA,优化SQL等)。 ### 总结 当Direct Path Read成为Top1等待事件时,首先需要分析AWR报告中的SQL Statistics部分,找出消耗I/O最多的SQL语句,并检查其执行计划。优化这些SQL语句(特别是减少全表扫描和排序)是根本的解决方法。其次,根据具体情况调整数据库参数(如PGA_AGGREGATE_TARGET,DB_CACHE_SIZE,以及控制直接路径读的参数)。最后,确保硬件I/O能力足够。 §§相关问题§§ 1. 如何从AWR报告中识别导致Direct Path Read等待事件的主要SQL? 2. 如何调整PGA_AGGREGATE_TARGET参数? 3. 在Oracle中如何禁用自动直接路径读特性? 4. 如何区分Direct Path ReadDirect Path Read Temp等待事件? </think>### Direct Path Read在AWR报告Top10中排第一的原因及解决方案分析 #### 一、核心原因分析 1. **大规模全表扫描/并行查询** - 当SQL执行**全表扫描大表**或**并行查询**时,Oracle会绕过Buffer Cache,直接从磁盘读取数据到PGA(私有内存),引发`direct path read`等待[^1][^2]。 - 典型场景: $$ \text{SELECT} \ \text{MAX(sal)} \ \text{FROM} \ \text{emp} \ \text{WHERE} \ \text{deptno} = 10 \quad \text{(全表扫描)} $$ $$ \text{SELECT} \ \text{/*+ PARALLEL(e 4) */} \ \text{COUNT(*)} \ \text{FROM} \ \text{emp} \ e \quad \text{(并行查询)} $$ 2. **PGA内存不足导致磁盘排序** - 当**排序(ORDER BY/GROUP BY)或哈希连接**的数据量超过`PGA_AGGREGATE_TARGET`时,会使用临时表空间进行磁盘排序,触发`direct path read temp`(但需区别于非temp的普通direct path read)[^2]。 3. **11g+自动优化特性** Oracle 11g及以上版本对串行全表扫描引入**自动直接路径读优化**(通过隐含参数`_serial_direct_read`控制),当优化器认为直接读效率更高时会启用此特性[^3]。 4. **I/O子系统性能瓶颈** - 磁盘I/O吞吐量不足(如低速SAN或过载存储) - ASM条带化配置不合理导致I/O分布不均 #### 二、关键解决方案 1. **SQL优化(根本措施)** - **减少全表扫描**:对大表查询添加过滤条件索引 ```sql CREATE INDEX emp_deptno_idx ON emp(deptno); ``` - **避免不必要的列读取**:使用`SELECT`具体字段而非`SELECT *` - **优化并行度**:调整不合理的`PARALLEL`提示或表并行度设置 ```sql ALTER TABLE emp PARALLEL 2; -- 降低并行度 ``` 2. **内存调整** - **增大PGA**:确保排序操作在内存完成 ```sql ALTER SYSTEM SET PGA_AGGREGATE_TARGET=8G; -- 根据总内存比例调整 ``` - **监控临时表空间使用**: ```sql SELECT * FROM V$TEMPSEG_USAGE; -- 检查磁盘排序会话 ``` 3. **控制直接路径读行为** - **禁用自动特性**(谨慎使用): ```sql ALTER SESSION SET "_serial_direct_read" = NEVER; -- 会话级禁用 ALTER SYSTEM SET EVENT='10949 TRACE NAME CONTEXT FOREVER'; -- 全局禁用(11g+) ``` 4. **I/O优化** - 使用更快的存储设备(如SSD) - 调整ASM条带大小: ```sql ALTER DISKGROUP DATA SET ATTRIBUTE 'au_size' = '4M'; -- 增大分配单元 ``` #### 三、诊断验证步骤 1. **定位高负载SQL** ```sql SELECT sql_id, executions, disk_reads, sql_text FROM V$SQLAREA ORDER BY disk_reads DESC; ``` 2. **检查执行计划** ```sql EXPLAIN PLAN FOR SELECT /*+ YOUR_SQL_HERE */ ...; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); ``` 3. **监控实时等待事件** ```sql SELECT event, total_waits, time_waited FROM V$SESSION_EVENT WHERE sid = (SELECT sid FROM V$MYSTAT WHERE ROWNUM=1); ``` > **关键结论**:通过SQL优化减少全表扫描是根本解决之道,内存和参数调整需配合业务场景验证效果[^1][^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值