awr中db file sequential read高通常反映sql访问路径或索引设计问题,而非磁盘慢;应重点分析物理读/执行次数比、回表信号、p1/p2定位对象及clustering_factor等。

AWR报告里db file sequential read排进Top 5,不等于磁盘慢——它大概率暴露的是SQL访问路径或索引设计问题,而不是I/O子系统故障。
看“Top SQL by Reads”别只盯time_waited
在AWR报告的“SQL ordered by Reads”部分,重点不是单条SQL的time_waited高,而是physical reads和executions的组合:如果某条SQL每次执行读几千块,但buffer gets远低于physical reads,说明缓存命中极差,且很可能在反复回表。
- 用
SELECT sql_id, disk_reads, executions, disk_reads/executions avg_reads_per_exec FROM dba_hist_sqlstat WHERE snap_id BETWEEN :begin_snap AND :end_snap ORDER BY disk_reads DESC补全AWR缺失的粒度 - 若
avg_reads_per_exec > 100且执行计划含TABLE ACCESS BY INDEX ROWID,基本可锁定回表瓶颈 - 注意
disk_reads包含索引块+表块,不能直接等同于“表扫描量”
查P1/P2反推对象时绕过current_obj#陷阱
v$active_session_history里的current_obj#可能为空或指向undo/temp段,不可靠;真正能定位物理读对象的,是等待事件的P1(文件号)和P2(块号)。
- 执行
SELECT segment_name, segment_type, owner FROM dba_extents WHERE file_id = &P1 AND &P2 BETWEEN block_id AND block_id + blocks - 1 - 若结果为空,检查是否
P2 = 1(读文件头,忽略)或统计信息过期(需重收集DBMS_STATS.GATHER_DICTIONARY_STATS) - 若返回多个
segment_name,优先查clustering_factor高的索引——它越接近表块数,回表越离散
执行计划里识别回表失控的三个信号
拿到sql_id后跑DBMS_XPLAN.DISPLAY_AWR('&sql_id'),不用全看,盯住这三处:
-
TABLE ACCESS BY INDEX ROWID行的Cost占总Cost 70%以上 → 回表已成主要开销 -
Rows预估列 vsA-Rows实际列相差超10倍 → 优化器低估回表行数,导致计划失准 - 紧邻
INDEX RANGE SCAN下方出现TABLE ACCESS BY INDEX ROWID,且无access([col])谓词下推 → 索引未覆盖查询列,必然回表
别盲目加大db_cache_size
把db_cache_size从8G拉到32G,对db file sequential read等待时间常无改善——因为单块读多发生在稀疏、不可预测的随机访问场景(如主键查用户档案),缓存再大也留不住冷块。
- 更有效的是让热数据“可预测”:对高频小表用
ALTER TABLE t STORAGE (BUFFER_POOL KEEP) - 对关键索引段,检查
dba_indexes.clustering_factor是否远大于num_rows,若是,考虑重建索引或调整字段顺序 - 若
physical reads中大量来自INDEX FAST FULL SCAN,确认是否真需要排序——FFS不走分支节点,适合count(*)类场景,但会绕过索引有序性
最易被忽略的一点:同一个segment_name在多次db file sequential read记录中高频出现,不代表它本身有问题,而可能说明访问它的SQL没走分区裁剪、用了低效绑定变量、或物化视图重写失败——得回到v$sql_plan里核对object_alias和实际current_obj#是否一致。











