嵌套块在PL / SQL过程中是否会对性能产生影响?

时间:2014-04-03 09:33:49

标签: oracle exception plsql

在PL / SQL过程中,我经常将语句包装在一个块中(即begin ... end),以便我可以从该语句中隔离异常。例如,如果我正在执行可能引发“no_data_found”的select,我可以在知道异常是由该语句引发的情况下处理它,但是让其他异常传播到该过程的主异常处理程序。

我想知道的是这些额外的块是否会对性能产生任何影响。我知道引发异常会对性能产生影响,所以我从不依赖异常作为控制流机制。但块本身是否有任何影响?

例如,如果性能之间存在任何差异:

procedure do_something
as
declare
  some_var number;
begin
  select some_value into some_var from some_table;
exception
when others then
  raise_application_error(-20000, 'Exception: ' || sqlerrm, true);
end do_something;

和此:

procedure do_something
as
declare
  some_var number;
begin
  begin
    select some_value into some_var from some_table;
  exception
  when no_data_found then
    some_var := -23; --some default value
  end;
exception
when others then
  raise_application_error(-20000, 'Exception: ' || sqlerrm, true);
end do_something;

(我知道这段代码是荒谬的,但我希望它能说明我的意思!)

我真正关心的是没有引发异常时的性能 - 当出现异常时我可以接受性能下降。

1 个答案:

答案 0 :(得分:5)

他们似乎不会:

set timing on
set serveroutput on

declare
  x number := 0;
begin
  dbms_output.put_line('No inner blocks');
  for i in 1..1000000 loop
    x := x + 1;
  end loop;
  dbms_output.put_line(x);
end;
/

anonymous block completed
Elapsed: 00:00:00.095
No inner blocks
1000000

在同一时间运行,每次都有一点变化,如:

declare
  x number := 0;
begin
  dbms_output.put_line('Nested inner blocks');
  for i in 1..1000000 loop
    begin
      begin
        begin
          begin
            x := x + 1;
          exception
            when others then
              raise;
          end;
        exception
          when others then
            raise;
        end;
      exception
        when others then
          raise;
      end;
    exception
      when others then
        raise;
    end;
  end loop;
  dbms_output.put_line(x);
end;
/

anonymous block completed
Elapsed: 00:00:00.090
Nested inner blocks
1000000

当然,编译器可能会删除冗余层,但我不确定它是否真的可以使用异常处理程序,因为它会影响结果。

我还没有看到嵌套块有多深的限制 - 文档只是说“块”可以嵌套'。您正在使用的模型,捕获特定错误并让其他人传播,这很好而且非常标准 - 尽管显然在您的人为例子中它是不必要的,但您知道这一点。