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从父表中删除时的工作原理,并检查子表中是否还没有孤立?
这是一个测试.我的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声明仍然没有完成,因为我需要输入这个响应,即大约十分钟.
| 归档时间: |
|
| 查看次数: |
3861 次 |
| 最近记录: |