优化查询以更新Oracle中的数百万个数据?

时间:2019-01-16 08:28:29

标签: sql oracle join sql-optimization

我有3张桌子:

  • 表A:1.7亿个数据
  • 表B:1.7亿个数据
  • 表C:1.3亿个数据
  • 表日志

如果 colA2 == colB2 ,我想用 colC4 的值更新 colA1 列> colB3 == colC3 。我创建了一个表格:

  • 表D:为了加速查询,存储了8000万个数据的 colB2 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万个数据。查询执行的速度不如第一次迭代

为什么会发生这种情况?脚本可以优化吗?

1 个答案:

答案 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:无法修改映射到未保留键的表的列

在您的情况下,您必须使用唯一索引支持表BC,以保证键保存视图

create unique index c_idx on c(col3);
create unique index b_idx on b(col2);

如果无法在生产性表上执行此操作,则只需使用临时表并在其上创建唯一索引,更新后的视图将仅连接两个表将更简单。