我必须逐行处理一个大表(2.5B记录)以跟踪两个变量。可以想象,这很慢。我正在寻找有关如何调整此过程的想法。谢谢。
declare
cursor c_data is select /* +index(data data_pk) */ * from data order by data_id;
r_data c_data%ROWTYPE;
lst_b_prc number(15,8);
lst_a_prc number(15,8);
begin
open c_data;
loop
fetch c_data into r_data;
exit when c_data%NOTFOUND;
if r_data.BATS = 'B' then
lst_b_prc := r_data.PRC;
end if;
if r_data.BATS = 'A' then
lst_a_prc := r_data.PRC;
end if;
if r_data.BATS = 'T' then
insert into trans .... lst_a_prc , lst_b_prc
end if;
end loop;
close c_data;
end;
问题实际上归结为找到有效的sql来跟踪每个BATS ='T'记录的BATS ='A'和BATS ='B'时的最新PRC值。
答案 0 :(得分:1)
有几种选择。最重要的是,您可能会为所有插件保留一个巨大的UNDO / REDO日志。你可以偶尔提交你的工作,比如每1000次插入。
另一个选择是使用SQL MERGE语句(或更简单的INSERT .. SELECT ..
语句),这将允许您的Oracle实例在集合而不是单个记录上运行。您的选择的执行计划可能会针对最佳INSERT
效果进行优化。
答案 1 :(得分:1)
如果我正确理解您的问题,请使用如下数据表:
create table data as
select 1 data_id, 'T' bats, 1 prc from dual union all
select 2 data_id, 'A' bats, 2 prc from dual union all
select 3 data_id, 'B' bats, 3 prc from dual union all
select 4 data_id, 'T' bats, 4 prc from dual union all
select 5 data_id, 'A' bats, 5 prc from dual union all
select 6 data_id, 'T' bats, 6 prc from dual union all
select 7 data_id, 'B' bats, 7 prc from dual union all
select 8 data_id, 'T' bats, 8 prc from dual union all
select 9 data_id, 'T' bats, 9 prc from dual;
您想为每个T插入一行,使用A和B的最后一个PRC值。这看起来像这样:
T data_id Last A Last B
--------- ------ ------
1 null null
4 2 3
6 5 3
8 5 7
9 5 7
此查询应该有效:
select data_id, last_A, last_B
from
(
select data_id, bats, prc
,max(case when bats = 'A' then prc else null end) over
(order by data_id
rows between unbounded preceding and current row) last_A
,max(case when bats = 'B' then prc else null end) over
(order by data_id
rows between unbounded preceding and current row) last_B
from data
)
where bats = 'T';
有了这么多数据,你可能想要使用直接路径写入和并行性。 性能在很大程度上取决于分析函数的排序是在内存中还是在磁盘上完成。优化内存可能非常困难,您可能需要使用DBA来允许您的进程尽可能多地使用内存而不会导致其他进程出现问题。