IO 等待高 / 磁盘延迟高
系统正在等待磁盘 IO。首先区分负载是读密集还是写密集,然后深入到原因:buffer cache 不足、全表扫描、checkpoint 风暴、IOPS 上限或溢出到临时空间。
IO 是读密集还是写密集?
使用文件 IO 统计信息确定等待发生在读取端(从磁盘读取数据)还是写入端(redo/checkpoint/数据写入)。这会将决策树一分为二。
SELECT function_name, small_read_reqs+large_read_reqs AS reads, small_write_reqs+large_write_reqs AS writes,
small_read_megabytes+large_read_megabytes+small_write_megabytes+large_write_megabytes AS mb
FROM v$iostat_function ORDER BY mb DESC;- 主要是读 IO
- 主要是写 IO
读 IO 为什么高?
过多的物理读主要有三个原因:buffer cache 太小(工作集放不进 RAM)、查询执行全表扫描,或大型排序/哈希操作溢出到临时空间。
SELECT ROUND((1-(pr.value/(dbg.value+cg.value)))*100,2) AS buffer_hit_pct
FROM v$sysstat pr, v$sysstat dbg, v$sysstat cg
WHERE pr.name='physical reads' AND dbg.name='db block gets' AND cg.name='consistent gets';
SELECT sql_id, disk_reads, executions FROM v$sql ORDER BY disk_reads DESC FETCH FIRST 10 ROWS ONLY;- buffer cache 命中率低,工作集放不下
- 查询执行全表扫描
- 大型排序/哈希溢出到临时空间
写 IO 为什么高?
写入端的瓶颈要么来自周期性的 checkpoint/刷写短时间内使磁盘饱和(checkpoint 风暴),要么来自存储缺乏维持负载所需的 IOPS/吞吐量。
SELECT event, total_waits, ROUND(time_waited/100,1) AS sec
FROM v$system_event
WHERE event IN ('log file parallel write','db file parallel write','checkpoint completed')
ORDER BY time_waited DESC;- checkpoint/刷脏集中爆发(checkpoint 风暴)
- 存储跟不上持续负载(IOPS 上限)
根本原因:buffer cache 不足
频繁访问的数据集(工作集)放不进 buffer cache,因此数据块不断被从磁盘重新读取。命中率低,物理读高。
根本原因:全表扫描
由于没有合适的索引,查询从头到尾扫描大表;这既导致大量物理读,又用无用的数据块污染缓存。
根本原因:排序/哈希溢出到临时空间
大型排序、hash join 或 group by 操作放不进工作内存,写入临时空间(temp/tempdb),产生大量读写 IO。
根本原因:checkpoint 风暴
脏页长时间累积,然后在短时间内批量写入磁盘;这些突发的写入浪潮会周期性地使 IO 饱和。
根本原因:IOPS / 吞吐量不足
存储缺乏满足负载所需读写请求的 IOPS 或带宽;队列深度和延迟持续偏高。