1

我有太多的 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 是个好主意吗?

4

2 回答 2

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;
于 2017-08-21T11:39:47.113 回答
0

Except your queries are very peculiar in terms of memory on your database server, option B is not going to increase the performance of the big query.

To ensure the above is true, try ask your DBA to check what happens in your databsae sever SGA at the time you perform the query. If a jam in the memory occurs, then it is worth trying to implement option B.

When I say "memory jams", I mean whole SGA memory is filled, making swap necessary on the server. If you do the inserts in a sequence, then SGA can be reused between the inserts.

于 2017-08-21T12:38:32.463 回答