Plsql 为什么PL/SQL批量DML在具有父子约束表的大型数据集上运行缓慢?

Plsql 为什么PL/SQL批量DML在具有父子约束表的大型数据集上运行缓慢?,plsql,oracle10g,bulk,dml,Plsql,Oracle10g,Bulk,Dml,我一直在试图弄清楚,对于记录表中有几十万条或更多记录的数据集,为什么PL/SQL清除脚本运行缓慢。在脚本执行之前,记录表的某个子集被标记为清除-大约75% 是什么原因导致删除Record_Part表的时间比其他表长这么多?是因为它处于3表父子层次结构的中间吗?我是否缺少索引或约束方面的知识?我可以做些什么来加速这个周期性清洗过程 这是一个Oracle 10g数据库 提前感谢您阅读我的问题 模式(部分): 记录表是父表 记录部分表是记录的子项(记录有许多记录部分) 记录人是记录人部分的子项(记录

我一直在试图弄清楚,对于记录表中有几十万条或更多记录的数据集,为什么PL/SQL清除脚本运行缓慢。在脚本执行之前,记录表的某个子集被标记为清除-大约75%

是什么原因导致删除Record_Part表的时间比其他表长这么多?是因为它处于3表父子层次结构的中间吗?我是否缺少索引或约束方面的知识?我可以做些什么来加速这个周期性清洗过程

这是一个Oracle 10g数据库

提前感谢您阅读我的问题

模式(部分):

  • 记录表是父表
  • 记录部分表是记录的子项(记录有许多记录部分)
  • 记录人是记录人部分的子项(记录人部分有多个记录人)
  • 典型比例为1:7:9(记录:记录部分:记录人)
记录

  • PK-sysid
  • 物理量
  • 未决
  • 正在清除
记录部分

  • PK-第二部分PK
  • FK-记录\u系统ID
记录人

  • PK-sysid
  • FK-第二部分pk
运行时

50000条记录

  • 记录所有人在1:40分钟内完成
  • 记录1:20分钟内完成的所有部分
  • 所有记录在10秒内完成
30万条记录

  • 记录9分钟内完成的所有记录
  • 记录2小时内完成的所有部分
  • 所有记录在20分钟内完成
200万条记录

  • 在1中记录所有完成的人员 时辰
  • 记录13分钟内完成的所有部分 小时(!)
  • 所有记录在8分钟内完成
索引和约束DDL

alter table Record add constraint record_REC_PK primary key (SYSID) using index tablespace DB_INDEX1;
alter table Record_Part add constraint RECPART_REC_PK primary key (Part_PK) using index tablespace DB_INDEX1;
alter table Record_Part add constraint RECPART_FK foreign key (RECORD_SYSID) references record (SYSID);
alter table Record_Person add constraint RECPERSON_REC_PK primary key (SYSID) using index tablespace DB_INDEX1;
alter table Record_Person add constraint RECPERSON_FK foreign key (Part_PK) references Record_Part (Part_PK);

CREATE INDEX REC_PURGE_IDX ON record (PURGE_IN_PROGRESS);
CREATE INDEX REC_PHYSID_IDX ON record (PHYSICALID);
CREATE INDEX REC_PENDING_IDX ON record (PENDING);
CREATE INDEX RECPART_RECORD_SYSID_IDX ON Record_Part (RECORD_SYSID);
CREATE INDEX RECPERSON_PARTPK_IDX on Record_Person (PART_PK);
脚本: (以下脚本中省略了时间戳打印)


能否在测试环境中禁用FK约束以查看这是否有帮助

另一种可能是将FK约束重新创建为可延迟,并在脚本开始时延迟约束,例如:

alter table Record_Part 
      add constraint RECPART_FK foreign key (RECORD_SYSID) 
                                references record (SYSID) DEFERRABLE;
alter table Record_Person 
      add constraint RECPERSON_FK foreign key (Part_PK) 
                                  references Record_Part (Part_PK) DEFERRABLE;

SET CONSTRAINTS ALL DEFERRED;
...run your purge
SET CONSTRAINTS ALL IMMEDIATE;
请注意,任何提交都会导致立即设置约束。每次提交后,必须重新发出第一个SETCONSTRAINTS语句


约束可能是我在这里的第一个怀疑。

检查此线程的第一个回复。正如Justin所指出的,您需要使用limit子句来获取固定数量的记录(通常使用100条,您可以将其参数化,并查看什么适合您的情况)


您真的是一次将200万个元素收集到一个集合中,而不是使用限制每次提取较少数量的元素吗?您是否跟踪了会话以查看时间花在了哪里?如果是这样,你能发布tkprof输出吗?谢谢Justin。我对脚本进行了测试,在批量收集中使用RONNUM限制来获取运行时,但我猜我没有考虑或认识到集合大小对执行速度的重要性。不要使用RONNUM限制。在你的批量收款中使用限制条款。谢谢你,贾斯汀。您对提交频率的评论也很有帮助。谢谢Rajesh,我现在正在运行测试,使用一个while循环围绕rownum限制的批量收集。问题-我应该多久提交一次?每100次,每1000次,还是仅仅在while循环后一次?在此脚本上下文中,提交速率如何影响速度?谢谢@kg-提交只会降低处理速度。仅在完成逻辑事务时提交。我假设这意味着,在您的情况下,除非您有特定的原因,否则您只会在流程结束时提交一次。由于清除脚本将与使用这些表的应用程序同时运行,因此我需要始终保持引用完整性。不过,我非常感谢关于推迟约束的信息,这对我将来会很有用。谢谢。可延迟约束仅限于会话-在其他会话中不会丢失约束检查。谢谢,我也不知道这一点!我将运行一个测试,看看延迟约束是否会加快脚本运行时间。
alter table Record_Part 
      add constraint RECPART_FK foreign key (RECORD_SYSID) 
                                references record (SYSID) DEFERRABLE;
alter table Record_Person 
      add constraint RECPERSON_FK foreign key (Part_PK) 
                                  references Record_Part (Part_PK) DEFERRABLE;

SET CONSTRAINTS ALL DEFERRED;
...run your purge
SET CONSTRAINTS ALL IMMEDIATE;