AWR不直接记录存储过程耗时,但可通过DBA_HIST_SQLSTAT等视图定位其内部慢SQL,结合SQL_TEXT、执行计划漂移、段级IO和绑定变量分析根因。

AWR 本身不直接记录存储过程执行耗时,但能精准定位其内部 SQL 的性能退化——关键在于把存储过程“拆开看”,而不是把它当黑盒。
查 DBA_HIST_SQLSTAT 锁定高消耗子语句
存储过程慢,90% 是某条内部 SQL 拖垮的。不能只查过程名,得顺着调用链找真实执行的 SQL_ID:
-
DBA_HIST_SQLSTAT是唯一能跨时段统计 SQL 执行指标的历史视图,重点看ELAPSED_TIME_DELTA、DISK_READS_DELTA和EXECUTIONS_DELTA - 用过程涉及的表名或关键字反向搜 SQL_TEXT:
SELECT sql_id, sql_text FROM dba_hist_sqltext WHERE UPPER(sql_text) LIKE '%TBL_ORDER%' - 若已知过程名(如
PKG_BATCH.PROC_CLOSE_MONTH),查v$session中正在执行该过程的会话,再关联sql_id;历史问题则必须依赖DBA_HIST_ACTIVE_SESS_HISTORY回溯 - RAC 环境下务必加
instance_number过滤,否则会混入其他节点的干扰数据
用 DBA_HIST_SQL_PLAN 验证执行计划是否漂移
同一 SQL_ID 在不同时间可能走完全不同路径——比如某天突然从 INDEX RANGE SCAN 变成 FULL TABLE SCAN,就是性能断崖的直接原因:
- 执行
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_AWR('sql_id', NULL, NULL, 'TYPICAL'))查历史计划,注意对比PLAN_HASH_VALUE是否变化 - 如果
PLAN_HASH_VALUE不同,说明执行计划已变更;相同也不代表安全——要细看Operation列是否出现FULL TABLE SCAN或INDEX FAST FULL SCAN - 特别警惕
ACCESS_PREDICATES和FILTER_PREDICATES:前者走索引,后者是扫完再过滤,性能差距可达百倍 - 11g 中若启用自适应游标共享(ACS),同一个 SQL_ID 可能对应多个
CHILD_NUMBER,需结合DBA_HIST_SQLSTAT的CHILD_NUMBER字段确认哪一版子游标贡献了高耗时
结合 DBA_HIST_SEG_STAT 确认热点对象是否被误扫
即使某条 SQL 显示走了索引,但如果它反复访问一张不该被高频扫描的大表,也可能是索引列设计不合理或谓词失效:
-
DBA_HIST_SEG_STAT统计的是段级 IO,绕过 SQL 粒度,直接暴露“谁被读爆了”:SELECT owner, object_name, object_type, physical_reads_total FROM dba_hist_seg_stat WHERE snap_id BETWEEN 12345 AND 12350 ORDER BY physical_reads_total DESC - 重点关注
OBJECT_TYPE = 'TABLE'且PHYSICAL_READS_TOTAL异常高的对象——如果这张表正是你存储过程中 UPDATE/SELECT 的主表,基本坐实索引缺失或失效 - 对比
LOGICAL_READS_TOTAL和PHYSICAL_READS_TOTAL比值:若物理读占比长期 > 20%,说明缓存效率差,不是参数问题就是 SQL 没走索引 - 注意
DBA_HIST_SEG_STAT默认只保留 SYSAUX 表空间中 WRH$_SEG_STAT 的数据,若 SYSAUX 空间不足或 AWR 快照被清理,可能查不到近期记录
别漏掉 DBA_HIST_SQLBIND 查绑定变量值是否触发隐式转换
存储过程里传参类型和表字段类型不一致,会导致索引完全失效——这种问题在 AWR 里不会报错,但 DBA_HIST_SQLBIND 能抓到真实传入值:
- 执行
SELECT name, position, datatype_string, value_string FROM dba_hist_sqlbind WHERE sql_id = 'xxx' AND snap_id = 12345 - 重点比对
value_string类型和目标字段类型:比如字段是VARCHAR2(20),但绑定值是NVARCHAR2,Oracle 就会强制转成TO_CHAR(:B1),索引失效 - 若
value_string显示为NULL或截断(如显示'ABC...),说明该绑定变量长度超限,也可能导致计划失真 - 这个视图默认不采集绑定变量(需设置
_cursor_bind_capture_area_size或开启SQL_TRACE的binds => TRUE),所以不是所有快照都有数据
真正难的不是查哪条 SQL 慢,而是判断“为什么这条 SQL 在这个存储过程中变慢了,但在别处不慢”——这往往卡在绑定变量值、统计信息时效性、甚至游标共享机制上,AWR 提供的是证据链,不是结论。


















