我有3张桌子:
如果 colA2 == colB2 和,我想用 colC4 的值更新 colA1 列> colB3 == colC3 。我创建了一个表格:
我还在表D中为 colB3 添加索引。
表日志用于存储每次迭代完成时的进度消息和完成时间(请参见脚本)。
当前我的更新脚本如下:
v_str_log := 'Begin updating';
p_write_to_log(v_str_log);
commit;
for data_list in
(
select distinct colC4
from tableC
)
loop
update tableA
set colA1 = data_list.colC4
where colA2 in
(
select colB2
from tableD
where colC3 = data_list.colC4
)
var_total := var_total + sql%rowcount;
v_str_log := 'Updated ' || sql%rowcount || ' for ' || card.sim_type || ' with total ' || var_total || ' rows.';
commit;
end loop;
我已经运行了该过程,并且在大约6个小时内完成了该过程。但是我从日志中发现,对于第一个循环,在3分钟内执行了300万个数据,但在随后的迭代中,大约20分钟内执行了500万个数据。查询执行的速度不如第一次迭代
为什么会发生这种情况?脚本可以优化吗?
答案 0 :(得分:1)
您必须查看Oracle的Updatable Join View功能-这正是您的用例。
首先连接子查询中的所有表(这将通过散列连接有效地完成,而没有缓慢的逐行循环)。
比UPDATE
子查询
示例
create table a
(col1 number,
col2 number);
create table b
(col2 number,
col3 number);
create table c
(col3 number,
col4 number);
insert into a values(null,1);
insert into b values(1,2);
insert into c values(2,1);
update (
select a.col1, c.col4
from a
join b on a.col2 = b.col2
join c on b.col3 = c.col3
)
set col1 = col4
;
请注意,UJV有一些前提条件。错过时会导致
ORA-01779:无法修改映射到未保留键的表的列
在您的情况下,您必须使用唯一索引支持表B
和C
,以保证键保存视图
create unique index c_idx on c(col3);
create unique index b_idx on b(col2);
如果无法在生产性表上执行此操作,则只需使用临时表并在其上创建唯一索引,更新后的视图将仅连接两个表将更简单。