Oracle удалить производительность - PullRequest
1 голос
/ 26 октября 2011

Скажем, у меня есть две таблицы:

create table parent (
  id number not null,
  constraint parent_pk primary key(id),
)

create table child (
  id number not null,
  parent_id number not null,
  constraint child_pk primary key(id),
  constraint child_fk1 foreign key(parent_id)
    references parent(id)
)

Родительская таблица - это, скажем, 3 миллиона записей. Теперь я запускаю оператор удаления:

delete from parent; //even without where clause

Не могли бы вы объяснить, что на самом деле происходит при выполнении этого оператора? Где не указана опция «ON DELETE CASCADE», насколько я понимаю, это означает, что удаление из родительской таблицы должно завершиться неудачей, если дочерняя таблица содержит ссылки на родительский идентификатор. Это означает, что перед удалением строки из родительской таблицы Oracle должен проверить, существуют ли какие-либо дочерние записи. Но это действительно очень медленно - это построчное удаление.

Я прав? Если нет, объясните, как работает Oracle при удалении из родительской таблицы, и проверьте, не осталось ли в дочерней таблице сирот?

Ответы [ 2 ]

7 голосов
/ 26 октября 2011

Вот тест.Моя таблица PARENT имеет 100000 строк.Для пустой таблицы CHILD (с индексом PARENT_ID) удаление занимает много времени:

SQL> set timing on
SQL> delete from parent;

100000 rows deleted.

Elapsed: 00:00:07.24
SQL> 

Давайте вставим несколько строк в CHILD.Это создаст одну строку для каждой строки в PARENT

SQL> insert into child
  2  select level, level from dual
  3  connect by level <= 100000;


100000 rows created.

Elapsed: 00:00:02.21
SQL> 

. Если мы сейчас удалим из родительского объекта, он мгновенно завершится неудачей.только одна запись в PARENT занимает немного больше времени ...

SQL> update child set parent_id=99999;

100000 rows updated.

Elapsed: 00:00:09.65
SQL> commit;

SQL> delete from parent;
delete from parent
*
ERROR at line 1:
ORA-02292: integrity constraint (APC.CHILD_FK1) violated - child record found


Elapsed: 00:00:07.32

Таймеры Wallclock, как известно, ненадежны, но это выглядит примерно столько же времени.И как это происходит, время для удаления таблицы PARENT без зависимостей внешнего ключа находится в том же приблизительном значении:

SQL> drop table child;

Table dropped.

Elapsed: 00:00:02.29
SQL> delete from parent;

100000 rows deleted.

Elapsed: 00:00:06.54
SQL> 

Таким образом, в основном, есть небольшие или никакие издержки для проверки ограничения внешнего ключа

Существует условие: это верно при условии, что столбец внешнего ключа проиндексирован .Я удалил индекс CHILD_FK1_I, и оператор delete from parent еще не закончил, когда мне потребовалось набрать этот ответ, то есть около десяти минут.

1 голос
/ 26 октября 2011

Поскольку ваша дочерняя таблица не имеет индекса для parent_id, oracle вынужден выполнять полное сканирование каждый раз, когда ему необходимо проверить наличие дочерних элементов. Другая проблема, которая может возникнуть из-за отсутствия этого индекса, когда вы планируете сделать это с несколькими процессами, - это конфликт. Без индексирования parent_id дочерняя таблица получит блокировку таблицы, где обычно блокируется только строка.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...