物理读高大概率导致查询变慢,因其代表从磁盘加载数据块的次数,每次涉及寻道、延迟和传输,比内存访问慢100–1000倍;缓存命中率低、buffer_cache过小、全表扫描、统计信息陈旧或buffer cache被清空等均是常见原因。
oracle查询变慢,直接看 physical reads 和 logical reads 是最有效的切入点之一——它们不是“指标装饰”,而是真实反映 i/o 压力和内存利用效率的硬信号。
为什么物理读高就大概率慢?
物理读代表从磁盘加载数据块到 buffer cache 的次数。每次物理读都涉及磁盘寻道、旋转延迟和传输,比内存访问慢 100–1000 倍。当 physical reads 显著高于 logical reads(比如比例 > 1:5),说明缓存命中率低,大量查询被迫等磁盘。
- 典型诱因包括:
buffer_cache设置过小、表/索引未被预热、大范围全表扫描未走索引、统计信息陈旧导致优化器选错执行路径 - 注意:
physical reads高 ≠ 一定有 SQL 写得差。也可能是业务突增导致热点数据被挤出缓存,或批量作业清空了buffer cache(如执行了alter system flush buffer_cache) - AWR 报告里重点关注 “Top SQL with Physical Reads” 和 “Instance Efficiency Percentages” 中的 “Buffer Nowait %”、“Redo NoWait %” —— 如果 Buffer Nowait %
逻辑读异常高但物理读低,问题在哪?
逻辑读(consistent gets)高而物理读(physical reads)低,通常意味着数据全在内存里,但 SQL 访问路径极低效——比如没走索引的全表扫描、嵌套循环 join 失控、或谓词无法下推导致大量行被反复过滤。
- 一个常见陷阱:
consistent gets高 +db block gets低 → 多半是只读查询,但逻辑读量远超实际返回行数(例如查 1 行却做了 10 万次 consistent gets),基本可断定执行计划用了全表扫描且表很大 - 检查 AWR 中该 SQL 的
Executions和Rows Processed比值:若每执行返回行数极少(如 -
consistent gets还包含回滚段访问(一致性读需构造前镜像),所以高逻辑读也可能暗示长事务或未提交更新阻塞了查询版本链
用 AWR 快速定位问题 SQL 的实操步骤
别从头翻 AWR HTML 报告。聚焦三处即可快速收敛:
- 打开 AWR 报告后,直奔 “SQL ordered by Gets” —— 这里按
logical reads排序,找出单次执行消耗最多 buffer 的 SQL;再对照 “SQL ordered by Reads” 看哪些 SQL 同时拉高了physical reads - 对目标 SQL,用
select * from dba_hist_sqlstat where sql_id = 'xxx' and snap_id between X and Y查它在多个快照区间内的disk_reads、buffer_gets、elapsed_time趋势,确认是否近期陡增 - 拿到 SQL ID 后,执行
select * from table(dbms_xplan.display_awr('sql_id')),重点看Operation列是否出现FULL TABLE SCAN,以及Rows与Starts的乘积是否远大于实际返回行数(即 “驱动行数爆炸”)
容易被忽略的底层细节
很多人盯着 physical reads 优化索引,却忘了 Oracle 的读行为受更底层机制约束:
-
db_file_multiblock_read_count直接影响一次物理读能拉多少块——设为 128 并不总比 16 快,尤其在 SSD 上可能因 IO 合并反而降低吞吐;应结合存储类型和ioseektim/iotfrspeed参数校准 - 即使开了 ASSM(自动段空间管理),高并发插入仍可能导致
buffer busy waits,表现为逻辑读高、等待事件堆积,此时需检查段头块争用,而非加索引 -
physical reads统计不含 direct path read(如并行查询、大数据量排序溢出),这类读不走 buffer cache,不会提升physical reads,但同样拖慢查询——需看direct path read等待事件



















