direct path read等待主要源于并行查询、PGA不足溢出至TEMP或串行扫描强制直读三类问题;需分别通过v$px_session、v$tempseg_usage及x$ksppi定位并针对性优化。
大量 direct path read 等待不是i/o本身慢,而是oracle主动绕开buffer cache、把数据直接读进pga的信号——它背后通常是并行查询、内存不足导致溢出到temp、或串行扫描被强制走直读这三类问题之一。
查是不是并行查询在“偷偷干活”
Oracle 12c默认对大表启用自动并行(尤其当表有PARALLEL属性或_parallel_statement_policy = AUTO时),每个PX从属进程(P00、P01等)都会触发direct path read,但父会话反而在PX Deq: Execute Reply上等,容易误判。
- 查
v$session_wait中event = 'direct path read'的会话,看program是否含P00、P01等字样 - 关联
v$px_session确认这些SID是否属于同一qcsid(即同一条SQL的并行执行) - AWR报告里重点看“SQL ordered by Parallel Executions”,别只盯Top SQL的执行时间
- 临时止血:给问题SQL加
/*+ NO_PARALLEL */;长期解决需评估是否真需要并行,或设_parallel_statement_policy = MANUAL
查PGA是否撑不住排序/哈希操作
当ORDER BY、GROUP BY或HASH JOIN中间结果太大,PGA放不下,就会写TEMP(触发direct path write temp),再读回来(触发direct path read temp)。这类等待常伴随v$tempseg_usage.segtype为SORT或HASH。
- 查
v$tempseg_usage,找segtype IN ('SORT', 'HASH')且session_addr匹配direct path read会话 - 查
v$sesstat中physical reads direct temp值高的会话,再反查其sql_id -
PGA_AGGREGATE_TARGET不能盲目调大——先看v$pgastat的cache hit percentage是否低于90%,bytes processed是否持续飙升 - 优先改写SQL:避免
SELECT *、加WHERE提前过滤、拆分大结果集
查_serial_direct_read是否被设成ALWAYS
这个隐含参数控制串行全表扫描是否走直读。默认是AUTO(Oracle按表大小和缓存热度自动决策),设成ALWAYS会导致小表也绕过Buffer Cache,徒增物理读。
- 查当前值:
SELECT ksppinm, ksppstvl FROM x$ksppi a, x$ksppcv b WHERE a.indx = b.indx AND ksppinm = '_serial_direct_read' - 如果是
ALWAYS,立刻改回AUTO:ALTER SYSTEM SET "_serial_direct_read" = AUTO; - 注意:该参数不支持
ALTER SESSION,只能实例级调整;设NEVER虽可禁用,但可能让大表扫描变慢,慎用
真正难定位的是混合场景:比如一条SQL既用了并行、又因PGA不足spill到TEMP,v$session_wait里看到的direct path read可能来自不同路径,必须结合file#(P1)、segment_type(通过x$ktsso关联)和sql_id交叉验证,否则容易治标不治本。


















