我有一个Oracle包,其输入参数为开始日期sysdate-365,结束日期为sysdate + 90。它找到从sysdate-365到sysdate + 90的每个日期,这是455天,然后它为每个日期循环,从主表中获取记录再次循环基于主表数据,从其他表获取值,做一些逻辑并插入工作台。完成需要10个多小时。
我想过使用dbms_scheduler来运行包并行,因为DBA不推荐这样做。任何人都可以建议任何其他方式来提高性能吗?
代码段:
loop for date range
select some_data from master_table where master_date = cursor.date;
loop for
select other_data from other_table where other_date = cursor.date
start with some_data
connect by other_parent = prior other_child;
select count(*) into v1cnt from third_table where third_date = cursor.date and third_data=other_data;
if v1cnt > 0 then
select third_data into variable1 from third_table where third_date = cursor.date and third_data=other_data;
else
variable1 = null;
end if;
select count(*) into v2cnt from fourth_table where third_date = cursor.date and fourth_data=other_data;
if v2cnt > 0 then
select fourth_data into variable2 from fourth_table where third_date = cursor.date and fourth_data=other_data;
else
variable2 := null;
end if;
do some other logic.
insert into working_table (variable1,variable2 ,cursor.date, fields from other logics);
end loop;
end loop;
答案 0 :(得分:8)
这是一种称为Row By Agonizing Row(RBAR)的数据库编程风格。您可以看到,SQL是一种基于集合的语言,旨在在单个操作中处理大量行。通过将您的逻辑分解为一系列操作,每个操作一次只能处理一行,您已经引入了大量的开销。
现在,并行运行此程序可能会减少总体运行时间,但这会使总资源使用率变得更糟:您仍然会在所有RBAR处理中咀嚼CPU,而且还有额外的管理并行查询的开销。难怪你的DBA反对它。很遗憾他们没有就如何修复你的代码提出建议。
我们很难给你一个实际的解决方案,因为我们不知道“做其他一些逻辑”背后隐藏着什么逻辑。但是,您发布的所有代码都是纯SQL。因此应该可以用INSERT INTO ... SELECT ...
替换所有PL / SQL。
实际的SELECT可能有点粗糙,可能需要子查询或WITH子句(find out more),但它将基于集合,并且可能比当前程序执行快几个数量级。如果您不知道如何编写复杂的查询,那么您应该点击DBA获取一些专家建议。