INSERT-SELECT(Oracle PL / SQL) - 性能问题

时间:2017-08-21 11:21:31

标签: oracle performance plsql insert-select

我有太多的SELECT语句,只有一个INSERT(可能是数百个)并且系统性能不佳。

我将一般性地解释发生了什么以及我正在寻找什么:

考虑Oracle PL / SQL中的以下两个伪代码,哪一个会提供最佳性能?

选项A:

INSERT INTO MyTable
  WITH Fields AS (
     SELECT Field1, Field2, ..., FieldN FROM TableA JOIN TableW .... WHERE <condition1>
     UNION ALL
     SELECT Field1, Field2, ..., FieldN FROM TableB JOIN TableX .... WHERE <condition2>
     UNION ALL
     SELECT Field1, Field2, ..., FieldN FROM TableC JOIN TableB .... WHERE <condition3>
     ....
     UNION ALL
     ....
     SELECT Field1, Field2, ..., FieldN FROM TableZZZ JOIN TableB .... WHERE <conditionN>

选项B:

BEGIN
  INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableA JOIN TableZ .... WHERE <condition1>
  INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableB JOIN TableW .... WHERE <condition2>
  INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableC JOIN TableH .... WHERE <condition3>
  ...
  INSERT INTO MyTable SELECT Field1, Field2, ..., FieldN FROM TableZZZZ JOIN TableX .... WHERE <conditionN>
END

我没有提供真正的表名,但我想知道:如果我将当前选项A更改为选项B,它会给我带来更好的表现吗?我的意思是,在这种情况下用很多INSERT语句替换UNION ALL是个好主意吗?

2 个答案:

答案 0 :(得分:2)

上下文切换和效果

几乎每个PL / SQL开发人员编写的程序都包含PL / SQL和SQL语句。 PL / SQL语句由PL / SQL语句执行器运行; SQL语句由SQL语句执行程序运行。当PL / SQL运行时引擎遇到SQL语句时,它会停止并将SQL语句传递给SQL引擎。 SQL引擎执行SQL语句并将信息返回给PL / SQL引擎(参见图1)。这种控制转移称为上下文切换,这些交换机中的每一个都会产生开销,从而降低程序的整体性能。

所以,请使用第三种方式:

create view MyView as select Field1, Field2, ..., FieldN from TableA join TableB .... where <condition1>

declare
  p_array_size pls_integer := 100;
  type         array is table of MyView%rowtype;
  l_data       array;
  cursor c is select * from MyView;    
begin
    open c;
    loop
    fetch c bulk collect into l_data limit p_array_size;

    forall i in 1..l_data.count
    insert into MyTable values l_data(i);

    exit when c%notfound;
    end loop;
    close c;
end;

答案 1 :(得分:0)

除了您的查询在数据库服务器上的内存方面非常奇怪之外,选项B不会提高大查询的性能。

要确保上述情况属实,请尝试让您的DBA检查执行查询时databsae服务器SGA中发生的情况。如果内存中出现卡纸,则值得尝试实现选项B

当我说“内存卡塞”时,我的意思是整个SGA内存已填满,需要在服务器上进行交换。如果按顺序执行插入,则可以在插入之间重用SGA。