DBMS_PROFILER在Oracle 19c中默认存在但分析表需手动执行proftab.sql创建,否则调用START_PROFILER会报ORA-06512;必须同一会话内启停且不可COMMIT;耗时定位依赖PLSQL_PROFILER_DATA等三表关联查询,图形工具依赖底层表完整性和权限。

DBMS_PROFILER 在 Oracle 19c 中默认已安装且可用,但配套的分析表(PLSQL_PROFILER_RUNS 等)不会自动创建,必须手动运行 proftab.sql;否则调用 START_PROFILER 会报 ORA-06512 错误。
确认 DBMS_PROFILER 是否就绪
直接在 SQL*Plus 或 SQL Developer 中执行:
desc dbms_profiler
如果返回函数列表(含 START_PROFILER、STOP_PROFILER),说明包存在;若报 “invalid object”,需用 SYS 执行:
-
@?/rdbms/admin/profload.sql(加载包) -
@?/rdbms/admin/proftab.sql(建表、序列、同义词) - 普通用户还需被授予对
PLSQL_PROFILER_*表的SELECT, INSERT, UPDATE, DELETE权限
用最小闭环捕获一次运行数据
关键点是:必须在**同一会话**中启动、执行、停止,且不能跨事务提交(COMMIT 会中断 profiler)。
推荐写法(带 run_number 输出,方便后续查):
SET SERVEROUTPUT ON
DECLARE
v_run_num PLS_INTEGER;
BEGIN
v_run_num := DBMS_PROFILER.START_PROFILER('my_proc_v1');
DBMS_OUTPUT.PUT_LINE('Run ID: ' || v_run_num);
-- 这里调用你的存储过程,例如:my_pkg.my_proc();
my_pkg.my_proc();
DBMS_PROFILER.STOP_PROFILER;
END;
- 不要在
BEGIN...END块外加COMMIT,否则STOP_PROFILER可能失败 - 注释字符串(如
'my_proc_v1')会记录在PLSQL_PROFILER_RUNS.COMMENT,用于后续筛选 - 如果过程内含自治事务(
PRAGMA AUTONOMOUS_TRANSACTION),profiler 无法跟踪其内部语句
从三张表里定位耗时行
瓶颈不在“哪个过程慢”,而在“哪一行 PL/SQL 代码最拖时间”。查法分两步:
第一步,找本次运行的 runid:
SELECT runid, run_date, comment FROM PLSQL_PROFILER_RUNS ORDER BY run_date DESC FETCH FIRST 1 ROW ONLY;
第二步,关联查具体行耗时(按 total_time 降序):
SELECT u.unit_name, d.line#, d.total_occur, d.total_time, d.min_time, d.max_time, u.text FROM PLSQL_PROFILER_DATA d JOIN PLSQL_PROFILER_UNITS u USING (unit_number, runid) WHERE d.runid = &your_runid AND d.total_time > 0 ORDER BY d.total_time DESC;
-
total_time是纳秒级,数值大不代表绝对慢——要结合total_occur看单次平均(total_time / total_occur) - 注意
text字段可能为空:这是因源码未保存或对象被加密;此时靠line#和上下文反推逻辑 - 高频小操作(如循环内
SELECT ... INTO)容易暴露为高total_occur+ 中等total_time,比单次长 SQL 更隐蔽
PL/SQL Developer 或 SQL Developer 的图形化捷径
如果你用的是 PL/SQL Developer,右键存储过程 → “Test” → 点击“Profile”按钮(不是“Execute”),它会自动完成启停+查表+渲染热力图。
SQL Developer 19c+ 版本也支持:View → DBA → Profiler Data,选中 run 后双击即可展开调用栈和行级耗时。
- 图形界面省去手写 SQL,但默认只显示前 1000 行;真遇到万行大过程,仍得回查
PLSQL_PROFILER_DATA - 界面里 “Average time” 列常被忽略,但它比
total_time更反映单次开销,尤其适合识别低频但致命的隐式类型转换或隐式游标打开 - 所有图形工具都依赖底层表数据,如果
proftab.sql没跑全(比如漏了同义词),界面会提示“no data found”而非报错,容易误判为没采集到
真正卡住的地方,往往不是显眼的 INSERT 或 UPDATE,而是循环里反复调用的函数、未绑定变量的动态 SQL、或 EXCEPTION 块中隐藏的 SELECT。DBMS_PROFILER 能把它们揪出来,但前提是——你得先让那三张表存在,并且权限干净。











