【问题标题】:Profiling stored functions in Oracle在 Oracle 中分析存储函数
【发布时间】:2015-07-24 10:06:40
【问题描述】:

在 Oracle11g 中是否可以分析在 SELECT ... INTO ... 语句中在 plsql 代码中调用的存储函数?

对于分析,我使用DBMS_HPROF 实用程序。在DBMSHP_FUNCTION_INFO 表中运行分析后,我可以看到除了在SELECT ... INTO ... 中调用的函数之外的所有内容。

【问题讨论】:

    标签: oracle plsql oracle11g profiling


    【解决方案1】:

    在 11g2 中,我的 HPROF 结果包括被称为

    的包函数中的行
    SELECT my_pkg.my_func(x) INTO y FROM dual;
    

    现在,我看不到每一行——通常只有 SQL 语句。例如,我在以下包中分析了“main_test”。

    ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL=0;
    
    CREATE OR REPLACE PACKAGE matt_t1 AS
      FUNCTION p (a NUMBER)
        RETURN NUMBER;
    
      PROCEDURE main_test;
    END matt_t1;
    
    CREATE OR REPLACE  TYPE my_num_tab_type IS TABLE OF NUMBER;
    
    CREATE OR REPLACE PACKAGE BODY matt_t1 AS
      FUNCTION p (a NUMBER)
        RETURN NUMBER IS
        x   NUMBER := 0;
        t my_num_tab_type;
       BEGIN
         t := new my_num_tab_type();
          for i in 1..10000 loop
              x := ln (x+i);
              t.extend();
             t(i) := x;
         END loop;
    
         SELECT SUM(column_value) INTO x FROM TABLE(t); 
        RETURN x;
      END p;
    
      PROCEDURE main_test IS
        x   NUMBER;
      BEGIN
        FOR i IN 1 .. 100 LOOP
          x   := matt_t1.p (i);
           DBMS_OUTPUT.put_line (x);
        END LOOP;
      END main_test;
    END matt_t1;
    

    在 HPROF 结果中,我看到了

    的条目
    SELECT SUM(column_value) INTO x FROM TABLE(t); 
    

    但不是,例如,

    x := ln (x+i);
    

    无论我将函数 p 调用为 SELECT INTO 还是直接通过 PL/SQL 分配一个值,我都会得到相同的结果。无论哪种方式,10,000 个自然对数的所有时间都存储在行的 HPROF 条目下

    FUNCTION p (a NUMBER)
    

    如果我直接分析对 MATT_T1.P() 的调用,我也会得到相同的结果。

    所以,我认为 HPROF 可能对它可以包含哪些类型的 PL/SQL 行有一些限制,但在我看来,调用方法 (SELECT..INTO) 与它无关。

    【讨论】:

      【解决方案2】:

      我在 DBMSHP_FUNCTION_INFO 中看到所有函数,例如 sql 函数,因为 dbms_hprof 不跟踪 sql 函数(如 ln、nvl... 等)。

      create or replace function addNum(p1 number,p2 number)  return 
      as
      begin 
       return p1+p2;
      end;
      
      BEGIN
        sys.DBMS_HPROF.START_PROFILING('TMP', 'test.trc');
      END;
      /
      
      declare 
       n number;
       n2 number;
       n3 number;
      BEGIN
        select sum(1),max(1),ln(1) into n,n2,n3 from dual;
        select max(addNum(1,level)) into n from dual connect by level<10;
      END;
      /
      
      BEGIN
        DBMS_HPROF.STOP_PROFILING;
      END;
      /
      

      让我们进入trc文件。
      select sum(1) into n from dual;被标记为P#C SQL."".""."__static_sql_exec_line6" #6 ,这意味着静态sql已经在第6行执行。
      select max(addNum(1,level)) into n from dual connect by level&lt;10;这个选择以P#C SQL."".""."__static_sql_exec_line7" #7开始在第6行然后它自己切换到 plsql VM 以计算 addnum 的结果。 __plsql_vm 和 ADDNUM 在 trc 中出现了 9 次。

      P#C SQL."".""."__static_sql_exec_line7" #7
      P#X 3338
      P#C PLSQL."".""."__plsql_vm"  <--switch context
      P#X 2
      P#C PLSQL."ALUKASIEWICZ"."ADDNUM"::8."ADDNUM"#a7f835561d3611ed #1  <-- execut function
      

      【讨论】:

      • 我认为 OP 想看到“返回 p1+p2;”在跟踪中也行。也就是说,他希望它跟踪到 addNum() 函数并报告在那里花费的时间。正如我在回答中指出的那样,配置文件只是不包含一些 PL/SQL 行。 SQL 语句似乎总是包含在内,但一个简单的“P1+P2”很可能被排除在外。但它的包含或排除似乎与它的调用方式无关(直接或通过 SELECT AddNum()..)。
      【解决方案3】:

      您是否尝试在存储函数中启用分析器?这可能会创建单独的跟踪(不同的 runId )。

      【讨论】:

      • 如何启用?
      • 将此添加到功能代码 dbms_hprof.start_profiling(location,filename,max_depth);和 dbms_hprof.stop_profiling .. 这只是为了弄清楚发生了什么.. 不确定这是否可以满足您程序的持续需求。
      • 我认为没有必要。 HPROF 确实包含来自内部函数调用的数据,即使函数调用是通过“SELECT f(x) FROM...”调用的。只是某些类型的 PL/SQL 行(例如,“X := X +1”)不包含在 HPROF 输出中。但是调用方法与包含或不包含什么无关。因此,在每个函数调用中启动单独的 HPROF 运行不会提供您已经从顶级 HPROF 运行中获得的更多详细信息。
      猜你喜欢
      • 2020-02-25
      • 1970-01-01
      • 1970-01-01
      • 2015-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-21
      • 1970-01-01
      相关资源
      最近更新 更多