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