レコード テーブルに数十万以上のレコードがあるデータセットに対して、この PL/SQL パージ スクリプトの実行速度が遅い理由を突き止めようとしています。スクリプトを実行する前に、Record テーブルの特定のサブセット (約 75%) にパージのフラグが立てられます。
Record_Part テーブルの削除に他のテーブルよりも時間がかかるのはなぜですか? 3テーブルの親子階層の真ん中だからでしょうか。インデックスまたは制約に関して、ここで知識が不足していますか? この定期的なパージ プロセスをスピードアップするにはどうすればよいですか?
これは Oracle 10g データベースです。
私の質問を読んでくれてありがとう。
スキーマ (部分):
- レコード テーブルは親テーブルです
- Record_Part テーブルは Record の子です (Record には多くの Record_Part があります)
- Record_Person は Record_Part の子です (Record_Part には多くの Record_Person があります)
- 一般的な比率は 1:7:9 (レコード:レコードの部分:レコードの人物) です。
記録
- PK - システム ID
- 物理ID
- 保留中
- パージ中
Record_Part
- PK - Part_pk
- FK - record_sysid
Record_Person
- PK - システム ID
- FK - Part_pk
ランタイム
50000 件のレコード エントリ
- record_person forall は 1:40 分で完了します
- record_part forall は 1 分 20 秒で完了します
- forall の記録は 10 秒で完了します
300000 レコード エントリ
- record_person forall は 9 分で完了します
- record_part forall は 2 時間で完了します
- forall の記録は 20 分で完了します
2000000 レコード エントリ
- record_person forall は 1 時間で完了します
- record_part forall は 13 時間 (!) で完了します
- forall の記録は 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;