plsql - 为什么 PL/SQL 批量 DML 对于具有父子约束表的大型数据集运行速度变慢?

标签 plsql oracle10g bulk dml

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

是什么导致 Record_Part 表的删除时间比其他表长得多?是不是因为在3表父子层级的中间?就索引或约束而言,我在这里是否遗漏了一些知识?我可以做些什么来加快这个定期清除过程?

这是一个 Oracle 10g 数据库。

提前感谢您阅读我的问题。

架构(部分):

  • 记录表是父表
  • Record_Part 表是 Record 的子表(Record 有很多 Record_Part)
  • Record_Person 是 Record_Part 的 child (Record_Part 有很多 Record_Person)
  • 典型比例为 1:7:9(记录:记录部分:记录人)

记录

  • PK - 系统标识
  • 物理编号
  • 待定
  • purge_in_progress

记录部分

  • PK - Part_pk
  • FK - record_sysid

记录人

  • PK - 系统标识
  • FK - Part_pk

运行时

50000条记录

  • record_person forall 在 1 分 40 分钟内完成
  • record_part forall 在 1 分 20 分钟内完成
  • 所有记录在 10 秒内完成

300000条记录

  • record_person forall 在 9 分钟内完成
  • record_part forall 在 2 小时内完成
  • 记录所有在 20 分钟内完成的记录

2000000条记录

  • record_person forall 在 1 内完成 小时
  • record_part forall 在 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);

脚本: (下面的脚本中省略了时间戳打印)

DECLARE

TYPE sSysid IS TABLE OF record.sysid%TYPE
    INDEX BY PLS_INTEGER;

TYPE physicalid IS TABLE OF record.physicalid%TYPE
    INDEX BY PLS_INTEGER;    

l_sid sSysid;
l_physicalid physicalid;

BEGIN
    SELECT sysid, physicalid
    BULK COLLECT INTO l_sid, l_physicalid
        FROM record
        where purge_in_progress = 1;

FORALL i IN l_sid.FIRST .. l_sid.LAST
    delete from record_person where Part_pk like concat(l_sid(i), '%') or Part_pk like concat(l_physicalid(i), '%');

commit;

FORALL i IN l_sid.FIRST .. l_sid.LAST
    delete from record_Part where record_sysid = l_sid(i);

commit;

FORALL i IN l_sid.FIRST .. l_sid.LAST
    delete from record where sysid = l_sid(i);

END;
/

commit;

最佳答案

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

http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::p11_question_id:5918938803188

关于plsql - 为什么 PL/SQL 批量 DML 对于具有父子约束表的大型数据集运行速度变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5277593/

相关文章:

oracle - 如何在 PL/SQL 中将 bool 值转换为数字?

Oracle10g XE : Why PLS_INTEGER cannot be a column type

sql - 基于国家值(value)的汇总

spring - Java 包 org.apache.poi.hssf.usermodel.* 的 Jar 实用程序

django - 多对多字段的批量更新

plsql - 关于程序,哪两种说法是正确的?

sql - 不同oracle数据的存储

oracle - 是否存在与DETERMINISTIC类似的PL/SQL编译指示,但仅适用于单个SQL SELECT的范围?

mysql - 意想不到的角色。 ( "\"附近

python - MongoDB,批量查找返回什么