direct path read等待剧增主因是Oracle主动绕过Buffer Cache的大块物理读,常见于12c自动并行查询触发PX进程、PGA不足导致TEMP溢出、或_serial_direct_read被误设为ALWAYS,需通过v$session_wait、v$px_session、v$tempseg_usage等视图交叉验证定位。
direct path read 等待剧增不是 I/O 本身慢,而是 Oracle 主动绕过 Buffer Cache 做大块物理读 —— 它本身是优化行为,但一旦失控,就会把存储打爆。关键不在“压测磁盘”,而在识别它为何被触发、谁在触发、是否真有必要。
查清是不是并行查询在后台偷偷拉起 PX 进程
oracle 12c 默认启用自动并行(_parallel_statement_policy = auto),只要表有 degree > 1 或统计信息显示“够大”,全表扫描就可能被悄悄并行化。每个 p00、p01 进程都会走 direct path read,且不进缓存,io 瞬间翻 n 倍。
实操建议:
- 查
v$session_wait中event = 'direct path read'的会话,看program是否含P00、P01等字样; - 关联
v$px_session,确认这些会话的qcsid是否指向同一个协调者(即同一条 SQL); - 在 AWR 报告中直接看 “SQL ordered by Parallel Executions”,找
Parallel Degree高、执行频次也高的语句; - 临时验证:对问题 SQL 加
/*+ NO_PARALLEL */提示重跑,观察physical reads direct是否骤降。
确认是否因 PGA 不足导致大量 TEMP 读写
当 ORDER BY、HASH JOIN 或 GROUP BY 的中间结果撑爆 PGA,Oracle 会 spill 到 TEMP 表空间 —— 先 direct path write temp,再 direct path read temp。这类等待常伴随 v$tempseg_usage.segtype IN ('SORT', 'HASH') 持续占用。
实操建议:
- 查
v$sesstat中physical reads direct temp值高的会话,再反查其sql_id; - 看该 SQL 执行计划,找
SPILL TO TEMP、TEMP TABLE TRANSFORMATION或USING TEMP标记; - 别只调
sort_area_size(12c 已废弃),重点看PGA_AGGREGATE_TARGET是否长期cache hit percentage (查 <code>v$pgastat); - 优先改写 SQL:删掉无用
SELECT *、加WHERE条件提前过滤、拆分大 JOIN。
检查 _serial_direct_read 是否被误设为 ALWAYS
_serial_direct_read 控制串行全表扫描是否走直接路径。默认是 AUTO(按对象大小和内存压力动态决定),但若被显式设为 ALWAYS,哪怕小表也会强制绕过 Buffer Cache —— 这等于废掉了缓存机制,所有全表扫描都变成本地磁盘 IO。
实操建议:
- 运行
SHOW PARAMETER _serial_direct_read,确认值不是ALWAYS; - 若确为
ALWAYS,立即改回AUTO:ALTER SYSTEM SET "_serial_direct_read" = AUTO;; - 注意:该参数是隐含参数,修改后无需重启,但会影响后续所有串行扫描行为;
- 不要靠调高
parallel_max_servers来“缓解”等待——这只会让并行从属进程更多,direct path read更密集。
避免用 DB_FILE_MULTIBLOCK_READ_COUNT 盲目调优
这个参数控制单次多块读的块数,影响 db file scattered read,但对 direct path read 几乎无感。因为后者走的是异步大块 IO(通常 1MB),由 _db_file_direct_io_count 或底层 OS max_io_size 决定,不受该参数约束。
实操建议:
- 别在
direct path read问题里碰DB_FILE_MULTIBLOCK_READ_COUNT—— 它解决不了根本; - 真正要调的是内存分配逻辑(PGA)、并行策略(_parallel_statement_policy)、以及 SQL 自身的数据访问模式;
- 如果发现大量
direct path read对应的是小表或低频查询,大概率是统计信息陈旧或直方图缺失,导致优化器误判“该走直接路径”。
direct path read 本身不是错误,它是 Oracle 在特定条件下做出的合理选择。问题往往出在“不该走的时候走了”,而定位依据必须是 v$session_wait + v$px_session + v$tempseg_usage + v$pgastat 的组合交叉验证,单看一个视图容易误判。











