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



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

上下文切换和性能

几乎每个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;

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

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

当我说"内存堵塞"时,我的意思是整个SGA内存都已满,因此需要在服务器上进行交换。如果按顺序进行插入,则可以在插入片段之间重复使用SGA。

最新更新