我一直在试图弄清楚为什么这个 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/