Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Database 使用ORACLE数据库请求提交每200个客户端的最佳方式是什么_Database_Oracle_Commit_Execution Time - Fatal编程技术网

Database 使用ORACLE数据库请求提交每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

我的数据库中有一个每天都会启动的请求。它用于删除最多约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_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表,它就不会出现太多提交综合症;希望这对你有用。祝你好运