3

レコード テーブルに数十万以上のレコードがあるデータセットに対して、この 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;
4

2 に答える 2

2

テスト環境で FK 制約を無効にして、それが役立つかどうかを確認できますか?

もう 1 つの可能性は、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;

COMMIT を実行すると、制約が即座に設定されることに注意してください。各コミットの後、最初の set Constraint ステートメントを再発行する必要があります。

ここで最初に疑うのは制約です。

于 2011-03-11T20:19:16.090 に答える
2

このスレッドの最初の返信を確認してください。Justin が指摘したように、制限句を使用して一定数のレコードをフェッチする必要があります (100 が一般的に使用されます。これをパラメーター化し、状況に応じて何が機能するかを確認できます)。

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

于 2011-03-11T20:43:41.647 に答える