V$ACTIVE_SESSION_HISTORY无法按IO请求类型聚合统计SQL,因其仅记录等待事件名称(如db file sequential read)及基础参数,不包含IO大小、asynch_io标志或access_method等物理IO特征字段;真正记录IO类型细节的是V$IOSTAT_FILE和DBA_HIST_IOSTAT_DETAIL视图,二者与ASH属不同采集通道且无直接关联键,强行JOIN会导致时间错位与结果失真。
直接查 v$active_session_history 无法按 io 请求类型(如 small read、large write)聚合统计 sql,因为 ash 本身不记录物理 io 量或读写大小分类——它只记录会话“在等什么”,比如 db file sequential read 或 direct path read,但不区分是 8kb 还是 1mb 的读请求。
为什么不能用 ASH 直接统计 IO 类型的请求量
ASH 的设计目标是捕捉“活跃会话状态”,不是 IO 计量。它的 event 字段只反映等待事件名称,p1/p2 参数虽可能含 block# 或 file#,但不携带 IO size、asynch_io 标志或 access_method 等 IO 特征字段。真正记录这些的是 V$IOSTAT_FILE 和 DBA_HIST_IOSTAT_DETAIL 视图,它们和 ASH 属于不同采集通道,无法通过 JOIN 关联出“某条 SQL 导致了多少 large_read_reqs”。
- ASH 中看到高频
db file scattered read,只能说明有大量多块读等待,但无法判断是全表扫描引发的小块聚合,还是并行查询触发的大 IO -
direct path read出现多,也不代表一定是大 IO——它可能是 128KB 的 direct read,也可能是 1MB 的 direct path read temp;ASH 不存这个粒度 - 试图在 ASH 上加
COUNT(*)按sql_id分组再关联DBA_HIST_IOSTAT_DETAIL,会因时间窗口错位、采样丢失、无外键关系而结果失真
替代路径:用 ASH 定位高 IO SQL,再用 IOSTAT 补充 IO 类型特征
必须分两步走:先靠 ASH 锁定“谁在大量等 IO”,再用 IO 统计视图验证其 IO 行为模式。关键不是强求单条 SQL 同时体现 event + IO type,而是建立可信的归因链。
- 第一步:从
V$ACTIVE_SESSION_HISTORY提取 IO 等待占比高的sql_id,筛选条件必须带wait_class = 'User I/O'且排除短于 1 秒的毛刺(加COUNT(*) > 5防止误判) - 第二步:对候选
sql_id,查V$SQL确认disk_reads、buffer_gets、io_cell_offload_eligible_bytes(Exadata 场景)等 IO 相关指标 - 第三步:查
V$IOSTAT_FILE或历史DBA_HIST_IOSTAT_DETAIL,按function_name(如 ‘FOB’、‘DBWR’、‘ARCH’)和filetype_name(如 ‘DATA FILE’、‘TEMP FILE’)看 IO 请求分布,确认是否与上一步的 SQL 操作对象匹配(例如:SQL 访问 USERS 表空间 → 查 USERS 对应 data file 的LARGE_READ_REQS是否突增)
实操中容易漏掉的关键过滤条件
直接跑 SELECT sql_id, event, COUNT(*) FROM v$active_session_history WHERE wait_class = 'User I/O' GROUP BY sql_id, event 会得到大量噪音。必须补上以下限制:
- 时间范围要窄:用
sample_time > SYSDATE - 1/720(过去 5 分钟),避免跨快照导致数据稀释 - 排除空闲等待:加
session_state = 'WAITING',否则ON CPU状态下也会被错误计入User I/O(虽然概率低,但存在逻辑漏洞) - 过滤无效 SQL:排除
sql_id IS NULL或sql_id = '0000000000000000',这类通常是递归调用或后台进程内部操作 - 注意
event的歧义性:log file parallel write属于System I/O,不是User I/O,但它会显著拖慢用户 SQL 的提交响应——需单独加wait_class IN ('User I/O', 'System I/O')并人工甄别
真正难的不是写出那条聚合 SQL,而是理解 ASH 的采样边界:它告诉你“此刻谁卡在 IO 上”,但不告诉你“这次卡住到底发出了多少个 1MB 异步读”。IO 类型特征必须回归到 IOSTAT 视图,而把这两类数据桥接起来的,是你对业务 SQL 访问模式(索引扫 vs 全表扫、临时表使用量、并行度设置)的判断,不是视图 JOIN。


















