oracle 正在生成批量更新查询

kcrjzv8t  于 2023-11-17  发布在  Oracle
关注(0)|答案(1)|浏览(127)

我目前正在研究存储过程,它利用游标中的游标在多源表和目标表之间插入和更新表。
基于游标数据的目标表的加载时间运行了一个小时,因为它为游标中的每条记录触发了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 ;

6yjfywim

6yjfywim1#

逐行处理-正如你发现的-很慢。如果你有嵌套循环,事情只会变得更糟,而不是更好。你提到的“批量处理”将-如果可能的话-完全跳过循环和游标,并在单个update(或-可能更好-merge语句)中完成所有事情。
你发布的代码(匿名PL/SQL块)是无效的;那里没有do关键字。顺便问一下,你真的在使用绑定变量(它们的名字前面有冒号:符号)吗?
因此:如果循环中没有额外计算或数据处理,请尝试组成一个表示源数据的查询。将该查询中的相应列连接到目标表的列,并 * 合并 * 结果。
这只是一个例子,它可能看起来像:

merge into target_table a
  using 
  -- that "large" single query begins here ...
  (select a.id, a.name, b.address, b.phone, c.country_name
   from users a join addresses b on a.user_id = b.user_id
                join countries c on c.country_id = b.country_id
  ) x
  -- ... and ends here
  on (a.id = x.id)
  when matched then update set
    a.name         = x.name,
    a.address      = x.address,
    a.phone        = x.phone,
    a.country_name = x.country_name;

字符串
merge还可以包含一个when not matched子句,它允许您insert包含在x子查询中的行,这些行在target_table中缺失。
这样一个面向集合的处理应该比你的循环中循环/逐行处理快得多。

相关问题