Oracle删除性能

and*_*hov 1 oracle performance foreign-keys

说我有两张桌子:

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)
)
Run Code Online (Sandbox Code Playgroud)

父表很大,比如300万条记录.现在我运行delete语句:

delete from parent; //even without where clause
Run Code Online (Sandbox Code Playgroud)

你能解释一下执行这个陈述时实际发生了什么吗?其中没有指定"ON DELETE CASCADE"选项,据我所知,这意味着如果子表包含对父ID的引用,则从父表中删除应该失败.所以这意味着在从父表中删除行之前,Oracle应检查是否存在任何子记录.但这真的非常慢 - 它是逐行删除.

我对么?如果没有,请解释Oracle从父表中删除时的工作原理,并检查子表中是否还没有孤立?

APC*_*APC 7

这是一个测试.我的PARENT表有100000行.对于空的CHILD表(PARENT_ID上有索引)删除需要这么长时间:

SQL> set timing on
SQL> delete from parent;

100000 rows deleted.

Elapsed: 00:00:07.24
SQL> 
Run Code Online (Sandbox Code Playgroud)

让我们在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> 
Run Code Online (Sandbox Code Playgroud)

如果我们现在从父母删除,它会立即失败.

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:00.14
SQL> 
Run Code Online (Sandbox Code Playgroud)

然而,如果我们将CHILD中的每条记录指向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
Run Code Online (Sandbox Code Playgroud)

众所周知,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> 
Run Code Online (Sandbox Code Playgroud)

因此,基本上,检查外键约束的开销很小或没有

有一个附带条件:如果外键列被索引,这是真的.我删除了CHILD_FK1_I索引,delete from parent声明仍然没有完成,因为我需要输入这个响应,即大约十分钟.