【问题标题】:dbms_output.put_linedbms_output.put_line
【发布时间】:2011-06-22 14:38:57
【问题描述】:

dbms_output.put_line 是否会降低 plsql 代码中的性能?

【问题讨论】:

    标签: performance oracle plsql dbms-output


    【解决方案1】:

    是的,这是需要执行的另一段代码,但除非实际打开输出,否则我认为开销很小。

    这是一个包含更多详细信息的 AskTom 问题:Is there a performance impact for dbms_output.put_line statements left in packages?

    【讨论】:

      【解决方案2】:

      这取决于您调用 dbms_output.put_line 的次数与您在 PL/SQL 中执行的其他操作的比率。

      【讨论】:

      • 另一个重要因素是使用什么样的表达式来构建参数,例如dbms_output.put_line(my_slow_function())
      【解决方案3】:

      每一行 额外的代码都会降低代码的性能。毕竟是要执行的额外指令,至少会消耗一些CPU。所以是的,dbms_output.put_line 会降低性能。

      真正的问题是:这行额外代码的好处是否超过了性能损失?只有你能回答这个问题。

      问候,
      抢。

      【讨论】:

        【解决方案4】:

        我使用日志表而不是 dbms_output。确保设置为自治事务,例如(根据您的需要进行修改):

        create or replace package body somePackage as
        ...
        procedure ins_log(
        i_msg in varchar2,
        i_msg_type in varchar2,
        i_msg_code in number default 0,
        i_msg_context in varchar2 default null
        ) IS PRAGMA AUTONOMOUS_TRANSACTION;
        
        begin
        
          insert into myLogTable
          (
          created_date,
          msg,
          msg_type,
          msg_code,
          msg_context
          )
          values
          (
          sysdate,
          i_msg,
          i_msg_type,
          i_msg_code,
          i_msg_context
          );
        
          commit;
        
        end ins_log;
        ...
        
        end;
        

        当然,请确保您创建了日志表。在您的代码中,如果您在一个循环中执行许多操作,您可能希望每个 x num 操作只记录一次,例如:

        create or replace myProcedure as
          cursor some_cursor is
          select * from someTable;
        
          v_ctr pls_integer := 0;
        
        begin
        
        for rec in some_cursor
        loop
          v_ctr := v_ctr + 1;
        
          -- do something interesting
        
          if (mod(v_ctr, 1000) = 0) then
            somePackage.ins_log('Inserted ' || v_ctr || ' records', 
                                'Log', 
                                 i_msg_context=>'myProcedure');
          end if;
        
        end loop;
        commit;
        
        exception
          when others then
          somePackage.ins_log(SQLERRM, 'Err', i_msg_context=>'myProcedure');
          rollback;
          raise;
        end;
        

        请注意,自治事务将确保您的日志 stmt 被插入,即使发生错误并且您回滚其他所有内容(因为它是一个单独的事务)。

        希望这会有所帮助...比 dbms_output 好得多;)

        【讨论】:

        • 这通常是一个很好的解决方案,但由于原始发布者担心开销,这可能会更糟。与调用 dbms_output.put_line 相比,处理自主事务所需的时间要长得多。
        • 您真的不希望生产代码中有一堆 dbms_output.put_lines。对于进入任何循环的代码来说尤其如此;)
        【解决方案5】:

        您可以调查conditional compilation,以便如果使用相应的选项编译过程,则DBMS_OUTPUT.PUT_LINE仅在预解析代码中。

        一个问题是,是否调用了 DBMS_OUTPUT.ENABLE。 如果是这样,DBMS_OUTPUT.PUT_LINE 中的任何值都将记录在会话的内存结构中。如果你继续往里面推送东西并且从不取出它(这可能是一些应用服务器连接的情况),你可能会发现几天后你的内存中有很多东西。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-05-13
          • 2012-12-05
          • 2020-06-06
          • 2018-10-24
          • 1970-01-01
          • 2018-09-23
          • 2011-08-25
          相关资源
          最近更新 更多