查v$active_session_history必须加动态时间窗口,因ASH内存仅保留约1小时且高负载下更短;应使用SAMPLE_TIME > SYSDATE - INTERVAL '3' MINUTE,避免写死时间字符串导致漏样;RAC环境须用gv$active_session_history以覆盖全实例。

查 v$active_session_history 必须加动态时间窗口
PL/SQL 执行快、样本少,ASH 内存只保留约 1 小时,高负载下可能只剩几分钟。写死时间(如 '2026-10-27 14:00:00')极易漏掉关键样本——尤其当卡顿发生在 14:02:59.8 而采样点只落在 .0/.1/.2 秒时。
正确做法是用 SAMPLE_TIME > SYSDATE - INTERVAL '3' MINUTE,覆盖最近 3 分钟足够抓到 PL/SQL 短时密集执行或解析卡点。RAC 环境必须用 gv$active_session_history,否则只看到当前节点,卡在 node2 就完全看不见。
- 别用
BETWEEN包死区间:边界采样不连续,容易断档 - 避免查
dba_hist_active_sess_history:它依赖 AWR 快照,默认每 10 秒刷一次,刚发生的样本还没入库 - 如果
plsql_entry_object_id = 0,说明是匿名块,得靠module和action辅助识别(比如module = 'SQL*Plus'+action = 'ANONYMOUS_BLOCK')
sql_id 为空时怎么定位 PL/SQL 卡点
ASH 中 sql_id IS NULL 是 PL/SQL 层耗时的明确信号——不是在跑 SQL,就是在做变量赋值、循环、条件判断、过程调用等纯 PL/SQL 工作。这时不能去 v$sql 查文本,得盯住 plsql_entry_object_id、plsql_subprogram_id 和 session_state。
-
session_state = 'ON CPU'且sql_id IS NULL→ 真正在跑 PL/SQL 逻辑,不是等 I/O 或锁 -
in_hard_parse = 'Y'比plsql_entry_object_id更可靠:动态 SQL(如EXECUTE IMMEDIATE)卡在硬解析阶段时,对象 ID 可能未稳定 -
event字段为空但session_state = 'ON CPU',基本可排除等待类问题,重点检查 PL/SQL 代码是否有低效循环、重复计算或未缓存的函数调用
区分 PL/SQL 层耗时和它内部 SQL 的耗时
同一个 plsql_entry_object_id 下,ASH 样本会混着两类:纯 PL/SQL(sql_id IS NULL)和它调用的 SQL(sql_id 非空)。直接按 sql_id 聚合会掩盖 PL/SQL 自身瓶颈。
- 先过滤出
sql_id IS NULL的样本,按plsql_entry_object_id和plsql_subprogram_id分组统计采样数,确认是否真有 PL/SQL 层热点 - 再查这些
plsql_entry_object_id对应的命名对象:SELECT object_name, procedure_name FROM dba_procedures WHERE object_id = &plsql_entry_object_id - 若发现某匿名块(
plsql_entry_object_id = 0)采样密集,且module是应用名(如'MyApp'),就该直接翻对应业务代码,而不是查执行计划
为什么 dbms_xplan.display_cursor 查不到 PL/SQL 的执行计划
dbms_xplan.display_cursor 只对有 sql_id 的语句有效。PL/SQL 块本身没有执行计划——它的“计划”就是字节码解释执行路径,Oracle 不暴露这个层级的详细路线图。你看到的慢,往往来自其中嵌套的 SQL,或 PL/SQL 运行时行为(比如频繁 context switch、大量 TO_CHAR 调用、未使用 BULK COLLECT)。
- 不要浪费时间在
display_cursor上查 PL/SQL 块;要查,就查它内部调用的sql_id(那些非空的样本) - 怀疑 PL/SQL 解释开销大?用
select * from v$sesstat s, v$statname n where s.statistic# = n.statistic# and n.name like '%recursive%' and s.sid = &sid看递归调用次数 - 真正难排查的是 PL/SQL 与 SQL 交织的场景:比如一个循环里每次
SELECT ... INTO,ASH 显示大量sql_id相同但session_state = 'ON CPU'的样本——这说明瓶颈不在 SQL 本身,而在 PL/SQL 层反复发起单行查询的模式
真实卡点常藏在 sql_id IS NULL 且 session_state = 'ON CPU' 的样本里,而多数人第一反应是查 SQL,结果绕一圈才发现慢的根本不是那条语句,而是它上面那层 PL/SQL 的写法。











