Database 使用ORACLE数据库请求提交每200个客户端的最佳方式是什么
我的数据库中有一个每天都会启动的请求。它用于删除最多约750个客户端的行。现在我们希望保留该请求,但我们需要每200个客户端提交一次 以下是原始请求:Database 使用ORACLE数据库请求提交每200个客户端的最佳方式是什么,database,oracle,commit,execution-time,Database,Oracle,Commit,Execution Time,我的数据库中有一个每天都会启动的请求。它用于删除最多约750个客户端的行。现在我们希望保留该请求,但我们需要每200个客户端提交一次 以下是原始请求: delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR); delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CL
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR);
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR);
如您所见,要删除的客户端id列表位于另一个表中。我们通过select请求获得它
select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR
该列表最多可以有750个客户端ID。
因此,每200个客户我都会这样做:
declare i number := 0;
begin
for r in (select ID_CLI from MKTMLF.TMP_ID_CLI_SUPPR)
loop
delete from MYSCHEMA.TABLE1 where id_cli = r.id_cli;
delete from MYSCHEMA.TABLE2 where id_cli = r.id_cli;
i := i+1;
if mod(i, 200) = 0 THEN
COMMIT;
end if;
end loop;
commit;
end;
但我的同事告诉我这是个坏主意,因为如果我们有750个ID要删除,这两个请求将有750次,因此750*2=1500个请求!他告诉我使用ROWNUM来获取前200个ID,然后提交其他200个ID等等。。。我试了一下,结果是这样的:
declare listTotal number := 0;
begin
select count(1) into listTotal from MKTMLF.TMP_ID_CLI_SUPPR;
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR where ROWNUM < 201);
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR where ROWNUM < 201);
commit;
if listTotal > 200 THEN
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 200 and r < 401);
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 200 and r < 401);
end if;
commit;
if listTotal > 400 THEN
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 400 and r < 601);
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 400 and r < 601);
end if;
commit;
if listTotal > 600 THEN
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 600 and r < 751);
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from (select tmp.*, rownum r from MKTMLF.TMP_ID_CLI_SUPPR tmp) where r > 600 and r < 751);
end if;
commit;
end;
所以我问自己,实现这一目标的最佳方式是什么?我发现第二种方法有点太复杂了,但可能更快?也许你有其他更好的方法吗?你说过你想每200次提交一次。。。因为有时候它在结束前就失败了 基于这些信息,我建议使用ERROR_LOGGING子句并将其保存在单个语句中。 我不认为每200次就把它拆散一次是处理这种情况的最好方法 以下是我的建议: 1为您的两个表创建一个错误表:
EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('TABLE1', 'TABLE1_ERRLOG');
EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('TABLE2', 'TABLE2_ERRLOG');
或者,您处理的每个表都有一个
这是一次性设置。。而且不需要每天重做
2让您的日常作业运行以下删除语句。。包括日志错误子句:
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
LOG ERRORS INTO TABLE1_ERRLOG ('Daily Delete1') REJECT LIMIT 750 ;
您可以将任何想要的数字作为拒绝限制。。我现在投了750英镑。。自从你提到你每天能处理750个?这将允许脚本尝试删除所有内容。。并报告所有失败的情况。如果您选择一个较低的数字,它将在命中那么多失败的删除后停止。调整以适应你的要求
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
LOG ERRORS INTO TABLE2_ERRLOG ('Daily Delete2') REJECT LIMIT 750 ;
3让作业在运行后查看这两个错误日志表,如果存在记录,则做出相应的响应
你可以调查他们,并处理他们,因为你会。。。然后,在需要重试时重新运行删除
注意:删除一个不存在的记录是可以的,它不会记录任何错误
请注意,对于INSERT、UPDATE和DELETE语句,存在此ERROR_日志记录子句。每个基表只需要1个错误表。。。不管您运行的INS/UPD/DEL是什么
换句话说。。。创建表1\u错误日志后。。。然后,您可以运行:
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
LOG ERRORS INTO TABLE1_ERRLOG ('Daily Delete1') REJECT LIMIT 750 ;
及
而且:
UPDATE MYSCHEMA.TABLE1 set some_col = some_value
where <some condition>
LOG ERRORS INTO TABLE1_ERRLOG ('Daily Update1') REJECT LIMIT 750 ;
它们都会将错误转储到同一个错误日志表中:TABLE1\u ERRLOG
您可以查看列:ORA_ERR_TAG$以查看它是Del、Ins还是Upd。。
(你发的评论)。。在上面的示例中,我使用了Daily Delete1、Daily Insert1和Daily Update1
甲骨文10:
日志错误子句示例:
甲骨文11:
日志错误子句示例:
你说你想每200个。。。因为有时候它在结束前就失败了 基于这些信息,我建议使用ERROR_LOGGING子句并将其保存在单个语句中。 我不认为每200次就把它拆散一次是处理这种情况的最好方法 以下是我的建议: 1为您的两个表创建一个错误表:
EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('TABLE1', 'TABLE1_ERRLOG');
EXECUTE DBMS_ERRLOG.CREATE_ERROR_LOG('TABLE2', 'TABLE2_ERRLOG');
或者,您处理的每个表都有一个
这是一次性设置。。而且不需要每天重做
2让您的日常作业运行以下删除语句。。包括日志错误子句:
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
LOG ERRORS INTO TABLE1_ERRLOG ('Daily Delete1') REJECT LIMIT 750 ;
您可以将任何想要的数字作为拒绝限制。。我现在投了750英镑。。自从你提到你每天能处理750个?这将允许脚本尝试删除所有内容。。并报告所有失败的情况。如果您选择一个较低的数字,它将在命中那么多失败的删除后停止。调整以适应你的要求
delete from MYSCHEMA.TABLE2 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
LOG ERRORS INTO TABLE2_ERRLOG ('Daily Delete2') REJECT LIMIT 750 ;
3让作业在运行后查看这两个错误日志表,如果存在记录,则做出相应的响应
你可以调查他们,并处理他们,因为你会。。。然后,在需要重试时重新运行删除
注意:删除一个不存在的记录是可以的,它不会记录任何错误
请注意,对于INSERT、UPDATE和DELETE语句,存在此ERROR_日志记录子句。每个基表只需要1个错误表。。。不管您运行的INS/UPD/DEL是什么
换句话说。。。创建表1\u错误日志后。。。然后,您可以运行:
delete from MYSCHEMA.TABLE1 where id_cli in (select ID_CLI from MYSCHEMA.TMP_ID_CLI_SUPPR)
LOG ERRORS INTO TABLE1_ERRLOG ('Daily Delete1') REJECT LIMIT 750 ;
及
而且:
UPDATE MYSCHEMA.TABLE1 set some_col = some_value
where <some condition>
LOG ERRORS INTO TABLE1_ERRLOG ('Daily Update1') REJECT LIMIT 750 ;
它们都会将错误转储到同一个错误日志表中:TABLE1\u ERRLOG
您可以查看列:ORA_ERR_TAG$以查看它是Del、Ins还是Upd。。
(你发的评论)。。在上面的示例中,我使用了Daily Delete1、Daily Insert1和Daily Update1
甲骨文10:
日志错误子句示例:
甲骨文11:
日志错误子句示例:
此表:MYSCHEMA.TMP_ID_CLI_SUPPR保存要删除的ID。一旦他们
从其他表中删除。。这张桌子发生什么事重要吗?也就是说,您是否可以通过删除已删除的表来清理此表。。只是好奇:为什么要求每200次提交一次??背后的逻辑/推理是什么?一旦我们删除了数据,每天我们都会用新的ID重新加载MYSCHEMA.TMP_ID_CLI_supper。为什么他们要每200个就提交一次?因为有时候它在结束前就失败了。在我的示例中,我只列出了两行说明,但该脚本中还有很多更新和删除内容。您使用的是Oracle的哪个版本?@Chriz我不建议使用autocommit:autocommit是sqlplus的客户端功能。。更像是解决问题的绷带,而不仅仅是正确地构建系统;此表:MYSCHEMA.TMP_ID_CLI_SUPPR保存要删除的ID。一旦从其他表中删除了它们。。这张桌子发生什么事重要吗?也就是说,您是否可以通过删除已删除的表来清理此表。。只是好奇:为什么要求每200次提交一次??背后的逻辑/推理是什么?一旦我们删除了数据,每天我们都会用新的ID重新加载MYSCHEMA.TMP_ID_CLI_supper。为什么他们要每200个就提交一次?因为有时候它在结束前就失败了。在我的示例中,我只列出了两行说明,但该脚本中还有很多更新和删除内容。您使用的是Oracle的哪个版本?@Chriz我不建议使用autocommit:autocommit是sqlplus的客户端功能。。更像是解决问题的绷带,而不仅仅是正确地构建系统;您的解决方案似乎很完美,我稍后会尝试实施它,因为准备这个需要一些时间。你说你要处理的每一张桌子有1张,我们要处理很多桌子,所以我必须花时间来做这件事,我必须说服我的同事这样做。@Siick:一开始可能会有更多的开销。。但是,随着时间的推移,收益应该是显而易见的:如果数据增长,此解决方案是可伸缩的。。更容易进行故障排除和维护,查找有问题的记录是很简单的-只需查看ERRLOG表,它就不会出现太多提交综合症;希望这对你有用。祝你好运您的解决方案似乎很完美,我稍后会尝试实施它,因为准备这个需要一些时间。你说你要处理的每一张桌子有1张,我们要处理很多桌子,所以我必须花时间来做这件事,我必须说服我的同事这样做。@Siick:一开始可能会有更多的开销。。但是,随着时间的推移,收益应该是显而易见的:如果数据增长,此解决方案是可伸缩的。。更容易进行故障排除和维护,查找有问题的记录是很简单的-只需查看ERRLOG表,它就不会出现太多提交综合症;希望这对你有用。祝你好运