awr中direct path read排进top 5说明大量sql正绕过buffer cache直接从磁盘读取大块数据,通常源于全表扫描、大结果集排序、hash join或并行查询;占比超5%需警惕,超20%已显著拖慢业务,应通过segments by direct physical reads、sql ordered by reads等视图定位问题表与sql,并优先检查缺失索引、审计表膨胀、临时空间不足及参数误调等根因。

direct path read高说明什么
AWR里direct path read排进Top 5,基本等于在说:有大量SQL正在绕过Buffer Cache,直接从磁盘读取大块数据。这不是“缓存没命中”的问题,而是Oracle主动选择跳过SGA、把数据读进PGA——通常意味着全表扫描、大结果集排序、Hash Join或并行查询正在密集发生。
关键不是它“发生了”,而是它“不该高频发生”。一个健康系统里,direct path read等待时间占比超过5%就该警惕;超过20%,大概率已拖慢业务响应。
先定位是哪张表/哪个SQL在触发
别猜,直接查AWR里的三个关键视图:
-
Segments by Direct Physical Reads:看哪些对象物理直读最多,比如AUD$、TBCM_CATALOGFILE这类表反复出现,就是靶心 -
SQL ordered by Reads:对应SQL_ID,找physical reads和executions都高的语句 -
SQL ordered by Elapsed Time:确认这些SQL是否真在拖慢用户,比如登录超时、报表卡死
注意:direct path read本身不带SQL_ID,必须靠关联physical reads反推。如果Segments by Direct Physical Reads里某张表占98%,而SQL ordered by Reads里全是访问它的SQL,基本可锁定问题源头。
常见根因与对应动作
查到具体表和SQL后,按优先级处理:
- 缺失索引:比如
WHERE F_OBJECTID = :1 AND F_PACKAGEPATH = :2没索引,400万行只能全扫——建复合索引(F_OBJECTID, F_PACKAGEPATH),立刻见效 - 审计表膨胀:
AUD$被频繁查询但无索引,且WHERE returncode != 0无法走索引——要么清理历史审计记录,要么改用DBA_AUDIT_SESSION视图(已带索引),或关闭不必要的审计 - 临时空间不足:
direct path read temp高,说明排序/Hash操作被迫写磁盘——查v$sort_segment,扩大TEMP表空间或设为自动扩展 - 参数误调:
_small_table_threshold被人为调小,导致中等表也被强制直读——恢复默认值(buffer cache的2%),不要轻易动隐含参数
特别提醒:有人会用alter system set event='10949 trace name context forever, level 1'关掉direct path read,这是饮鸩止渴。它只是让SQL退回缓存读,但逻辑没变,Buffer Cache会被迅速挤满,引发free buffer waits或latch: cache buffers chains新问题。
为什么加了索引还无效
建完索引发现direct path read没降,常见原因:
- 执行计划没更新:统计信息过期,
DBMS_STATS.GATHER_TABLE_STATS没跑,优化器仍选全表扫描 - 谓词失效:SQL里写了
TO_CHAR(timestamp, 'YYYY-MM-DD HH24:MI:SS') >= ...,函数导致索引失效——改用timestamp >= SYSDATE - 30/24/60 - 绑定变量窥探失准:第一次硬解析用了低选择性值,后续都沿用错误计划——考虑加
/*+ BIND_AWARE */hint或启用自适应游标共享 - 表太大+并发太高:单次直读IO压力不大,但100个会话同时扫同一张大表,I/O队列瞬间拉满——这时光靠索引不够,得拆分查询粒度或加应用层缓存
最易被忽略的一点:direct path read常是果,不是因。它背后藏着设计缺陷——比如用大表做实时状态轮询、审计日志当业务表用、批量作业没分页。解决它,终究要回到业务逻辑本身。











