【发布时间】:2019-01-16 08:28:29
【问题描述】:
我有 3 张桌子:
- 表 A:1.7 亿条数据
- 表 B:1.7 亿条数据
- 表 C:1.3 亿条数据
- 表日志
如果 colA2 == colB2 和 ,我想用 colC4 的值更新列 colA1 >colB3 == colC3。我创建了一个表:
- 表 D:8000 万数据存储 colB2 和 colC3 以加快查询速度。
我还在表 D 中添加了 colB3 的索引。
Table Log 用于存储每次迭代完成时的进度消息和完成时间(参见脚本)。
目前我的更新脚本是这样的:
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 小时内完成。但是我从日志中发现,对于第一个循环,300 万条数据执行了 3 分钟,但几次迭代之后,500 万条数据在大约 20 分钟内执行。查询的执行速度不如第一次迭代快
为什么会这样?脚本可以优化吗?
【问题讨论】:
-
看MERGE INTO指令
-
考虑到要更新数百万条记录,为什么不使用 BULK COLLECT 或 FORALL 呢?看看this
-
并考虑从内部循环中删除提交指令。这也为您节省了大量时间。如果在执行过程中发生崩溃 - 假设在 30 000 000 条记录之后,这 30 000 000 条异常记录仍将等待提交。
-
@q4za4 非常感谢您关于从循环中删除提交的建议。它将执行时间从大约 4 小时减少到 2 小时。 :)
-
@q4za4 MERGE INTO 命令会显着改善上面的查询还是仅仅为了可读性?
标签: sql oracle join sql-optimization