oracle存储瓶颈排查关键看db file sequential/scattered read的持续占比、单次延迟及背后sql是否“该读”:若av rd(ms)<5ms但等待事件仍高,多为索引缺失或统计信息过期所致,而非磁盘本身慢。
oracle存储瓶颈的排查不能只看i/o等待事件是否排在top 5,关键要看db file sequential read和db file scattered read的持续占比、单次延迟、以及背后sql是否真的“该读”——很多情况下,是索引缺失或统计信息过期导致本该走索引的查询被迫全表扫描,把存储拖垮。
怎么看db file sequential/scattered read是否真代表存储慢?
这两个事件高,并不等于磁盘本身慢。它们只是“数据库在等块回来”,原因可能是:
- 存储响应确实慢(如SAN延迟>10ms、机械盘随机IO能力不足)
- SQL没走索引,反复扫大表——逻辑上不该读这么多块
- 缓冲区太小,热数据反复进出内存,放大了物理读
- 统计信息过期,优化器误判走全表扫描
验证方法:查IO Stats by Filetype章节,看Av Rd(ms)(平均读取毫秒数)。若<5ms但db file scattered read仍占Top 1,基本可排除硬件问题,转向SQL和索引。
如何定位真正造成高物理读的SQL?
别只盯着SQL ordered by Physical Reads——它只列总量,容易被低频大读SQL带偏。更有效的是结合两个维度:
- 查
SQL ordered by Gets中Buffer Gets per Exec>100,000且Rows Processed per Exec<100的语句:说明大量逻辑读却只返回几行,极可能缺索引 - 查
SQL ordered by Elapsed Time中Executions>1000/小时且Elapsed Time per Exec>1s的语句:高频+慢,对I/O压力是乘数效应 - 用
plan_hash_value对比不同快照里的执行计划,确认是否因统计信息更新导致计划退化(比如从索引范围扫描变成全表扫描)
示例:SELECT * FROM sensor_log WHERE device_id = :1执行了2800次/小时,每次逻辑读12万,但只返回3行——加INDEX(device_id)后逻辑读降到420,物理读归零。
哪些AWR指标能交叉验证存储负载真实性?
单看等待事件容易误判,必须结合IO统计与实例效率指标交叉比对:
-
Physical Reads/sec持续>500(SSD环境)或>150(传统盘),且Av Rd(ms)同步上升 → 存储真实承压 -
Buffer Hit Ratio<90% +Physical Reads高 → 不是存储慢,是db_cache_size不够或热点数据没缓存住 -
Write Clusters/sec(在IO Stats by Function里)异常高,但log file sync等待也高 → 日志写入成为瓶颈,不是数据文件存储问题 -
DBWR checkpoints频繁触发,且Checkpoint Not Complete告警出现 → 检查点跟不上脏块生成速度,常因fast_start_mttr_target设得太小或日志组太少
注意:IO Stats by Filetype里要区分Data File、Temp File、Log File——临时表空间读高,可能是排序/哈希连接溢出,跟主存储无关。
真正难识别的不是“存储慢”,而是“本不该发生的读”。AWR里db file sequential read和db file scattered read的数值本身没意义,必须绑定到具体SQL、执行计划、缓冲区命中率三者才能下结论。很多团队花时间换SSD,结果发现只是某张表缺一个复合索引。











