db file parallel read 是单个进程并行读取多个离散数据块时的i/o等待事件,非并行查询引起;19c中因_batch_table_access_by_rowid默认启用、高聚簇因子索引回表、预读失控或i/o响应慢而加剧,优化核心是减少离散读次数与提升单次i/o效率。
db file parallel read 不是并行查询导致的,而是单个进程批量读多个离散块时触发的 i/o 等待;在 oracle 19c 中,它常因高聚簇因子索引回表、预读(prefetch)失控或 i/o 子系统响应慢而放大,优化重点不在“开并行”,而在减少离散物理读次数和提升单次 i/o 效率。
为什么 19c 里 db file parallel read 突然变多
Oracle 19c 默认启用 _optimizer_batch_table_access_by_rowid(默认 TRUE),这会让优化器对大批量 ROWID 回表尝试合并为 batch I/O,触发 db file parallel read。但若目标表的索引聚簇因子(clustering_factor)远大于表行数,这些 ROWID 对应的数据块在磁盘上高度离散,一次 batch 读可能跨多个文件、几十个非连续块,I/O 延迟叠加,等待时间陡增。
常见诱因包括:
- 执行计划含
TABLE ACCESS BY INDEX ROWID BATCHED,但底层表未按索引列物理聚集 - 使用了
INDEX RANGE SCAN+ 高选择性谓词,返回大量 ROWID 后集中回表 - 隐式 prefetch 被激活(如
_db_block_prefetch_limit未设为 0),尤其在 PGA 内存充足时更激进 - 数据文件分布在同一 LUN 或共享存储卷上,物理 I/O 竞争加剧
调整隐藏参数关闭 prefetch 并限制 batch 行为
Oracle 19c 中不推荐全局禁用 prefetch,但可针对问题 SQL 或会话级精准抑制。关键参数需在 ALTER SESSION 中设置,避免影响整体实例行为:
- 关闭预读:执行
ALTER SESSION SET "_db_block_prefetch_limit" = 0;和ALTER SESSION SET "_db_block_prefetch_quota" = 0; - 禁用 batch 回表:执行
ALTER SESSION SET "_optimizer_batch_table_access_by_rowid" = FALSE;—— 这会强制退回到传统逐个 ROWID 的db file sequential read,虽单次等待短,但总次数上升,需配合索引优化 - 限制非连续多块读数量:执行
ALTER SESSION SET "_db_file_noncontig_mblock_read_count" = 4;(默认值通常为 8–16),降低每次db file parallel read提交的 requests 数
注意:_db_file_noncontig_mblock_read_count 在 19c 中仍有效,但仅影响非连续块读场景,对全表扫描类的 db file scattered read 无作用。
检查并重组织高聚簇因子索引与表
高 clustering_factor 是 db file parallel read 持续偏高的根本原因之一。确认方式:
SELECT index_name, clustering_factor, num_rows, blevel FROM dba_indexes WHERE table_name = 'V_RPT_PLYEDR_INSRNC' AND owner = 'YOUR_SCHEMA';
若 clustering_factor 接近或超过 num_rows * 2,说明物理顺序与索引顺序严重偏离。此时:
- 重建索引本身无效(
ALTER INDEX ... REBUILD不改变表数据物理顺序) - 必须重组织表:用
CREATE TABLE ... AS SELECT /*+ ORDER BY indexed_col */ ...或ALTER TABLE ... MOVE ONLINE ORDER BY indexed_col;(19c 支持 ONLINE) - 重建索引后再次收集统计信息:
EXEC DBMS_STATS.GATHER_TABLE_STATS('YOUR_SCHEMA', 'V_RPT_PLYEDR_INSRNC');
移动表时若指定 ORDER BY 列与主查询的索引前导列一致,能显著降低后续 range scan 的 block 跨度,从而减少单次 db file parallel read 的 blocks(P2)和 requests(P3)值。
IO 分布与存储层协同调优
即使 SQL 和参数都调优完毕,若所有数据文件都在同一组物理磁盘(如单个 RAID5 卷),db file parallel read 的 P1(files)值高仍会导致 I/O 队列堆积。验证方法:
SELECT file_id, file_name, bytes/1024/1024 mb FROM dba_data_files WHERE tablespace_name IN ( SELECT tablespace_name FROM dba_segments WHERE segment_name = 'V_RPT_PLYEDR_INSRNC' );
优化动作包括:
- 将热点表空间的数据文件分散到不同 ASM diskgroup 或不同挂载点(Linux:
df -h查看) - 确认存储是否启用异步 I/O:
SHOW PARAMETER disk_asynch_io应为TRUE;若使用文件系统,filesystemio_options应为SETALL或ASYNC - 避免在 OLTP 系统中把 undo、temp、data 文件混布在同一 LUN ——
db file parallel read多文件(P1)等待会直接受交叉干扰
真正容易被忽略的是:19c 的自动内存管理(AMM)下,若 pga_aggregate_target 设置过高,反而会助长 prefetch 行为,建议结合 V$PGASTAT 中的 cache_hit_percentage 和 bytes_used 值动态收敛 PGA 规模,而非一味调大。











