必须用gv$filestat并过滤inst_id才能在rac环境准确统计,因v$filestat仅返回当前实例数据且file#非全局唯一,直接join会漏统计或错关联;单实例可用v$filestat,但始终应以file_id=file#为关联条件,避免文件名匹配误差。
直接查 v$filestat 关联 dba_data_files 就能拿到每个数据文件的物理读写次数、块数和耗时,但必须注意 rac 环境下要用 gv$filestat 并显式过滤 inst_id,否则数据会混杂。
为什么不能只用 v$filestat 简单 JOIN?
因为 v$filestat 中的 file# 是实例级编号,而 dba_data_files.file_id 是数据库级唯一标识。两者在单实例下通常一致,但在 RAC 多节点环境中,不同实例可能对同一物理文件分配不同 file#;更关键的是,v$filestat 默认只返回当前实例的统计,若不加 inst_id 过滤就 JOIN,会漏掉其他节点的 IO,或误把不同节点的同名文件当成本地文件统计。
正确做法是:
- 单实例:用
v$filestat即可 - RAC:必须用
gv$filestat,且 WHERE 条件中明确指定inst_id = <your_instance_id></your_instance_id> - 始终用
file_id(来自dba_data_files)与file#(来自gv$filestat)关联,而不是依赖文件名字符串匹配——文件名可能重复或含路径差异
phyrds 和 phyblkrd 差很大,说明什么?
这不是异常,而是 Oracle 多块读(如全表扫描)和单块读(如索引查找)共存的自然结果。真正要看的是比值 phyblkrd / phyrds:
- 比值 ≈ 1:以单块读为主,典型于高并发索引访问,IO 散、延迟敏感,应关注
db file sequential read等待事件 - 比值 ≥ 8(甚至到 64 或 128):多块读占主导,常见于大表扫描、并行查询,吞吐量比单次延迟更重要
- 如果
phyrds很高但phyblkrd很低:说明频繁发起小读请求却总未命中缓存,大概率是 buffer cache 命中率低,需检查Buffer Hit Ratio或 SQL 是否未走索引
如何排除干扰项,让结果反映真实数据文件 IO?
v$filestat 统计的是“交由操作系统处理的 IO”,不是最终落盘次数,中间经过 OS buffer、ASM 条带、存储缓存等多层。所以结果偏高或延迟偏低都属正常。要让它真正指向瓶颈,必须过滤掉非数据文件:
- 加
WHERE df.file_name IS NOT NULL:排除已删除但元数据残留的条目 - 避免 JOIN
v$tempfile或v$logfile:它们对应不同视图(v$tempstat、v$logstat),混在一起会扭曲解读 - 临时文件(
TEMP表空间)和撤销文件(UNDOTBS)IO 模式完全不同,需单独分析,不应和数据文件放同一张表里对比 - 若发现
SYSTEM或SYSAUX文件 IO 显著偏高,优先检查是否应用在这些表空间建了业务对象——这属于配置错误,不是性能问题
最易被忽略的一点:这些统计值是自实例启动以来的累计值,不是实时速率。想看“当前压力”,得取两个时间点的差值(比如 AWR 快照间),或者用 AWR 的 File I/O Statistics 部分——它自带归一化和排序,还能显示平均等待毫秒(Av I/O Wait (ms)),比裸查 v$filestat 更贴近真实响应体验。











