先确认sql逻辑问题而非直接换磁盘:若db file sequential/scattered read占db time超15%且avg wait超标,需优先检查awr中“sql ordered by reads”与“sql ordered by elapsed time”重叠的高读sql,结合执行计划判断是否全表扫描或索引低效;再查dba_hist_filestatxs中avg_read_ms(注意readtim单位为百分之一秒,需×10换算)及文件归属表空间,排除temp/users等非索引使用场景。

db file sequential/scattered read高,先别急着换磁盘
这两个等待事件占总DB Time超过15%,且Avg Wait (ms)超标(SSD > 3ms、SAN > 10ms),才值得怀疑I/O子系统。但更常见的情况是SQL逻辑问题:比如某条SQL执行了200次全表扫描,每次读几千块,db file scattered read自然飙升——这不是磁盘慢,是它被反复狂扫。
检查步骤:
- 翻AWR报告的“SQL ordered by Reads”章节,找Physical Reads占比最高的SQL ID
- 交叉核对该SQL在“SQL ordered by Elapsed Time”里的排名:如果也靠前,说明执行路径本身有问题
- 用
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('sql_id'))看执行计划,确认是否出现FULL或低效的INDEX RANGE SCAN - 查
DBA_HIST_FILESTATXS里对应文件的avg_read_ms:若avg_read_msphyrds极高,基本排除硬件问题
File IO Stats里哪个文件被读爆了?重点看三列
AWR报告中“I/O Stat by Filetype”页面只给汇总,真要定位物理瓶颈,得盯紧Physical Reads、Avg Read Time (ms)和Tablespace这三列。
典型线索:
-
Physical Reads单个文件占全库70%以上 → 压力集中,不是整体存储问题 -
Avg Read Time (ms)持续>15ms → 真实I/O延迟,需结合DBA_HIST_FILESTATXS验证 -
Tablespace列全是USERS或SYSTEM→ 很可能没走索引;如果是TEMP→ 排序/哈希溢出到磁盘
注意:READTIM单位是百分之一秒(centiseconds),不是毫秒。直接除PHYRDS会得出错误平均值。
log file sync高?先查user commits每秒多少
log file sync等待时间高,不等于redo写慢。真正关键指标是每秒提交次数。
运行这条SQL获取真实压力:
SELECT ROUND(SUM(CASE WHEN NAME = 'user commits' THEN VALUE END) / 3600, 2) AS commits_per_sec
FROM v$sysstat
WHERE NAME IN ('user commits','user rollbacks');
结果解读:
- 50–200/s:需关注事务粒度,检查是否
INSERT; COMMIT;式高频小事务 - > 200/s:提交风暴,优化方向是合并事务或调整应用逻辑,不是调存储
再比对log file parallel write的Avg Wait (ms):两者数值接近才指向LGWR写盘瓶颈;若log file sync远高于后者,问题大概率在Data Guard同步、RAC SCN传播或应用频繁提交。
为什么查DBA_HIST_FILESTATXS总得不到想要的文件名?
这个视图默认只有file#和ts#,没有文件路径。直接JOIN v$datafile和v$tablespace才能补全信息。
常用查询模板(替换&snap_id为实际快照ID):
SELECT ts.name ts_name, df.name file_name,
f.phyrds, ROUND(f.readtim / NULLIF(f.phyrds, 0), 2) avg_read_ms,
f.phywrts, ROUND(f.writetim / NULLIF(f.phywrts, 0), 2) avg_write_ms
FROM dba_hist_filestatxs f
JOIN v$tablespace ts ON f.ts# = ts.ts#
JOIN v$datafile df ON f.file# = df.file#
WHERE f.snap_id = &snap_id
AND f.phyrds > 0
ORDER BY avg_read_ms DESC;
容易踩的坑:
- 漏掉
NULLIF(f.phyrds, 0)→ 除零报错 - 没加
f.snap_id = &snap_id→ 扫全历史,性能极差 - 没JOIN
v$datafile→ 只看到file#,无法定位物理文件 - 误把
readtim当毫秒用 → 实际是百分之一秒,需乘以10才是毫秒
单个文件avg_read_ms > 20ms且phyrds稳定高位,才是真正需要干预的I/O热点;偶尔一次200ms毛刺,avg_read_ms可能还不到2ms,这种瞬时问题得靠v$iostat_file实时抓取。











