我目前正在研究存储过程,它利用游标中的游标在多源表和目标表之间插入和更新表。
基于游标数据的目标表的加载时间运行了一个小时,因为它为游标中的每条记录触发了insert。
我创建了另一个子过程来使用这个插入格式处理这个用例。假设我有10个记录为游标提取,批量插入语句看起来像这样,
execute immediate 'insert into target_table ( col1, col2, col3, col4, col5) values
('100','101','102','abc','def'),
('200','201','202','abc2','def2')
.
.
.
.
('1000','1001','1002','1003','def10')'; --tenth record
字符串
执行时间大大降低到分钟~ 5分钟。
类似地说,我有10条记录从游标中取出,我想更新目标表中的10条记录,如果我在游标中编写一个update语句,它将分别为所有记录执行update。
我如何处理更新操作来进行单次批量更新(类似于我上面分享的插入操作)而不是单次更新?
示例如下:
CUR_C1 CURSOR FOR
select col1, col2, col3, col4, col5 from source_table1;
OPEN CUR_C1
FOR CUR_REC in CUR_C1
DO
v1 := col1;
v2 := col2;
v3 := col3;
v4 := col4;
v5 := col5;
UPDATE target_table
set
col2 = :v2,
col3 = :v3,
col4 = :v4,
col5 = :v5
where
col1 = :v1;
END CUR_REC ;
CLOSE CUR_C1 ;
型
1条答案
按热度按时间6yjfywim1#
逐行处理-正如你发现的-很慢。如果你有嵌套循环,事情只会变得更糟,而不是更好。你提到的“批量处理”将-如果可能的话-完全跳过循环和游标,并在单个
update
(或-可能更好-merge
语句)中完成所有事情。你发布的代码(匿名PL/SQL块)是无效的;那里没有
do
关键字。顺便问一下,你真的在使用绑定变量(它们的名字前面有冒号:
符号)吗?因此:如果循环中没有额外计算或数据处理,请尝试组成一个表示源数据的查询。将该查询中的相应列连接到目标表的列,并 * 合并 * 结果。
这只是一个例子,它可能看起来像:
字符串
merge
还可以包含一个when not matched
子句,它允许您insert
包含在x
子查询中的行,这些行在target_table
中缺失。这样一个面向集合的处理应该比你的循环中循环/逐行处理快得多。