Oracle删除操作需要永远执行

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

我正在尝试使用这段代码,但它需要几个小时才能运行:

create table tmp$_mkemp_2 (id number generated by default on null as identity primary key, c1 varchar2 (30), c2 varchar2 (30))
/

set timing on serveroutput on size unlimited linesize 32767 pagesize 50000 trimspool on tab off feedback on heading on verify on
define svTableName = tmp$_mkemp_2
define svInsertHowMany = 500000
define svFetchRate = 2000
define svUpdateWhichMod = 2
define svDeleteWhichMod = 10
col ts format a20
col cnt format a10
<<s01_row_by_row_rbr_dml>> begin <<rbr_loop>> for iRec in (select dbms_random.string ('p', 10) c1, level id from dual connect by level <= &svInsertHowMany) loop
          insert into &svTableName (c1) values (iRec.c1);
          if mod (iRec.id, &svFetchRate) = 0 then commit; end if; end loop rbr_loop; commit;
     <<update_loop>> for iUpdateRec in (select id, c1 from &svTableName) loop
          update &svTableName set c2 = substr (c1, 1, 2) || ' ## ' || id where mod (id, &svUpdateWhichMod) = 0 and id = iUpdateRec.id;
          if mod (iUpdateRec.id, &svFetchRate) = 0 then commit; end if; end loop update_loop; commit;
     <<delete_loop>> for iDeleteRec in (select id, c1 from &svTableName) loop
          delete &svTableName where id = iDeleteRec.id and mod (iDeleteRec.id, &svDeleteWhichMod) = 0;
          if mod (iDeleteRec.id, &svFetchRate) = 0 then commit; end if; end loop delete_loop; commit;
     end s01_row_by_row_rbr_dml;
/
select to_char (sysdate, 'mm/dd/yyyy hh24:mi:ss') ts from dual
/
select count (0) cnt from &svTableName
/

字符串
当我从另一个会话中检查表计数时,它显示450,000,这意味着delete_loop已经完成。这需要大约10分钟,* 但该过程在那之后继续运行数小时 *。

为什么工作完成后,原始会话中的事务仍在继续运行?

这个问题在较小的数据集上似乎是可以重现的。例如,对于50,000行,删除大约在1分钟后完成(表现在显示为有45,000行),但整个过程需要6分钟才能完成。
我知道这是一种错误的数据处理方法,但我想了解这种方法的运行时性能的细节。

neskvpey

neskvpey1#

这一行代码:

for iDeleteRec in (select id, c1 from &svTableName) loop
          delete &svTableName where mod (id, &svDeleteWhichMod) = 0;

字符串
循环了50万次。在每个循环中,你都在做一个单独的删除操作,你唯一的 predicate 是一个取模函数。你是否省略了and id = iDeleteRec.id predicate 来镜像你为更新所做的事情?
当前代码删除的内容超出了您的预期,而且无法使用索引来执行此操作。

相关问题