awr报告不统计存储过程本身i/o,只记录其内部sql语句的独立统计;需通过高io的sql_id反查dba_source或结合dba_hist_active_sess_history的plsql_entry_object_id定位调用过程。
awr 报告里没有专门针对“存储过程”的 i/o 统计,sql statistics 段只按 sql_id 聚合,不识别存储过程封装关系——你看到的只是过程内部执行的每条 sql 的独立统计。
为什么 SQL Statistics 里找不到存储过程名
Oracle 不在 AWR 中记录 PL/SQL 单元(如 PROCEDURE、FUNCTION)的执行上下文。即使某条高 I/O 的 SELECT 是在 pkg_order.calc_total() 里调用的,AWR 只会把它归到该语句自身的 SQL_ID 下,不会打上“来自 calc_total”标签。
-
v$sql和 AWR 的DBA_HIST_SQLSTAT都只存语句文本、执行计划、I/O 累计值,不存调用栈 - 存储过程本身不产生物理 I/O,真正读写磁盘的是它内部执行的 DML/SELECT
- 若过程含动态 SQL(
EXECUTE IMMEDIATE),语句文本可能被截断或标准化,更难关联源过程
如何间接定位存储过程引发的高 IO
核心思路:先锁住高 I/O 的 SQL_ID,再反查其是否属于某个过程体。
- 从 AWR 报告的
SQL ordered by Reads或SQL ordered by Physical Read Requests找出SQL_ID和对应语句文本 - 用
DBA_SOURCE全文搜索该语句片段(注意模糊匹配,因格式化/换行/注释可能不同):SELECT owner, name, type, line FROM dba_source WHERE UPPER(text) LIKE '%WHERE order_date > SYSDATE-7%' AND type = 'PROCEDURE' ORDER BY owner, name, line;
- 检查
v$session+v$open_cursor实时抓取正在执行该 SQL 的会话,并看PLSQL_ENTRY_OBJECT_ID:SELECT s.sid, s.sql_id, o.object_name, o.object_type FROM v$session s JOIN v$open_cursor c ON s.saddr = c.ses_addr JOIN dba_objects o ON c.OWNER = o.owner AND c.OBJECT_NAME = o.object_name WHERE s.sql_id = '&sql_id';
(仅对当前活跃会话有效)
DBA_HIST_ACTIVE_SESS_HISTORY 能补什么缺
这是唯一能带 PL/SQL 上下文的历史视图,但需确认采样精度和保留策略。
-
DBA_HIST_ACTIVE_SESS_HISTORY中的PLSQL_ENTRY_OBJECT_ID和PLSQL_ENTRY_SUBPROGRAM_ID字段可回溯到过程名 - 需关联
DBA_OBJECTS解析对象名:SELECT h.sample_time, o.object_name proc_name, h.sql_id, h.event FROM dba_hist_active_sess_history h JOIN dba_objects o ON h.plsql_entry_object_id = o.object_id WHERE h.sql_id = '&sql_id' AND h.snap_id BETWEEN &start_snap AND &end_snap;
- 注意:默认每秒采样一次,但只保留 1 小时(
ASH)或最多 8 天(DBA_HIST_*),且PLSQL_ENTRY_*字段在非活跃路径下可能为空
容易被忽略的关键点
真正耗 I/O 的往往不是主逻辑,而是过程里隐式触发的递归 SQL —— 比如 DBMS_STATS 自动收集、REF CURSOR 绑定变量未复用、或 PRAGMA AUTONOMOUS_TRANSACTION 引发额外日志写入。这些 SQL 在 SQL Statistics 里独立存在,但和表层过程无文本关联,必须结合 Top Events 和 IO Stats by Function 交叉判断。











