Почему PL / SQL Bulk DML работает медленно для больших наборов данных с ограниченными родительскими и дочерними таблицами? - PullRequest
3 голосов
/ 11 марта 2011

Я пытался выяснить, почему этот скрипт очистки PL / SQL работает медленно для наборов данных, в которых таблица записей содержит несколько сотен тысяч или более записей.Перед выполнением сценария определенное подмножество таблицы записей помечается для очистки - около 75%.

Что вызывает удаление таблицы Record_Part так долго, как в других таблицах?Это потому, что он находится в середине иерархии родитель-потомок с 3 таблицами?Я пропускаю некоторые знания здесь с точки зрения индексов или ограничений?Что я могу сделать, чтобы ускорить этот периодический процесс очистки?

Это база данных Oracle 10g.

Заранее спасибо за чтение моего вопроса.

Схема (частичная):

  • Таблица записей является родительской таблицей
  • Таблица Record_Part является дочерним элементом Record (запись имеет много записей Record_Part)
  • Record_Person является дочерним элементом Record_Part (Record_Part имеет много записей Record_Person)
  • Типичное соотношение составляет 1: 7: 9 (запись: record_part: record_person)

Запись

  • PK - sysid
  • physicalid
  • в ожидании
  • purge_in_progress

Record_Part

  • PK - Part_pk
  • FK - record_sysid

Record_Person

  • PK - sysid
  • FK - Part_pk

Runtime

50000 записей записей

  • запись record_person завершается за 1:40 мин
  • запись record_part завершается за 1:20 мин
  • запись завершается за 10 секунд

300000 записей записей

  • запись_персонала завершается за 9 минут
  • запись_часть завершается за 2 часа
  • запись завершается за 20 минут

2000000 записей записей

  • запись record_person завершается за 1 час
  • запись record_part завершается за 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;

Ответы [ 2 ]

2 голосов
/ 11 марта 2011

Проверьте первый ответ в этой теме. Как указал Джастин, вам нужно использовать предложение limit для извлечения фиксированного количества записей (обычно используется 100, вы можете параметризовать это и посмотреть, что подходит для вашей ситуации).

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

2 голосов
/ 11 марта 2011

Можно ли отключить ограничения 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;

Обратите внимание, что любой COMMIT приведет к немедленной установке ограничений. Вам нужно будет перевыпускать первый оператор ограничений набора после каждой фиксации.

Ограничения были бы моим первым подозреваемым здесь.

...