在單個刪除語句(在單個plsql塊中執行)上效率更高的表上級聯刪除?Oracle級聯刪除
7
A
回答
17
什麼cascade delete
確實是發出個別刪除語句。
檢查下面的測試案例:
create table parent
(parent_id number,
parent_name varchar2(30),
constraint parent_pk primary key (parent_id) using index);
create table child
(child_id number,
parent_id number,
child_name varchar2(30),
constraint child_pk primary key (parent_id, child_id) using index,
constraint child_fk01 foreign key (parent_id)
references parent (parent_id)
on delete cascade;
);
insert into parent
(parent_id, parent_name)
select object_id, object_name from dba_objects where rownum <= 10000;
begin
for i in 1..10
loop
insert into child
(child_id, parent_id, child_name)
select i, parent_id, parent_name
from parent;
end loop;
end;
/
exec dbms_stats.gather_table_stats (tabname => 'PARENT', cascade => true);
exec dbms_stats.gather_table_stats (tabname => 'CHILD', cascade => true);
exec dbms_monitor.session_trace_enable;
alter table child drop constraint child_fk01;
alter table child add constraint child_fk01 foreign key (parent_id)
references parent (parent_id) on delete cascade enable novalidate ;
delete from parent;
rollback;
在跟蹤文件,你會發現這樣一行:
delete from "<MY_SCHEMA_NAME>"."CHILD" where "PARENT_ID" = :1
END OF STMT
PARSE #6:c=0,e=182,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=1293353992514766
EXEC#6:c=0,e=545,p=0,cr=2,cu=32,mis=1,r=10,dep=1,og=4,tim=1293353992515354
EXEC#6:c=0,e=233,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992515644
EXEC#6:c=0,e=238,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992515931
EXEC#6:c=0,e=252,p=0,cr=2,cu=32,mis=0,r=10,dep=1,og=4,tim=1293353992516229
EXEC#6:c=0,e=231,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992516507
EXEC#6:c=0,e=227,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992516782
EXEC#6:c=0,e=244,p=0,cr=2,cu=32,mis=0,r=10,dep=1,og=4,tim=1293353992517072
EXEC#6:c=0,e=219,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992517337
EXEC#6:c=0,e=236,p=0,cr=3,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992517622
EXEC#6:c=0,e=235,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992517921
EXEC#6:c=0,e=229,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992518196
EXEC#6:c=0,e=246,p=0,cr=2,cu=32,mis=0,r=10,dep=1,og=4,tim=1293353992518487
EXEC#6:c=0,e=234,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992518767
EXEC#6:c=6999,e=570,p=0,cr=2,cu=30,mis=0,r=10,dep=1,og=4,tim=1293353992519383
這是Oracle發出delete語句對CHILD
每個它的記錄在PARENT
中刪除。
一個不同的問題將是其中的兩個是更有效的:
DELETE FROM CHILD WHERE PARENT_ID = 1;
DELETE FROM PARENT WHERE PARENT_ID = 1;
VS
DELETE FROM PARENT WHERE PARENT_ID = 1;
都與on delete cascade
啓用。令人驚訝的是,在上面的第一種情況下,Oracle將在子表上探測外鍵索引,以查看是否存在需要級聯的行。如果不存在行,Oracle不會執行級聯刪除。
5
您不能比較這兩個選項。它不是一個性能問題,而是更多的設計和結構。
如果您使用主鍵/外鍵來設計數據庫,那麼使用級聯刪除將比使用級聯刪除更容易進行刪除,而不是手動搜索哪裏有外鍵在哪個列和表上並生成機械SQL語句。
主要優點的級聯,刪除功能是它可以讓你減少SQL語句需要執行刪除操作
0
如果你想級聯刪除,並沒有定義外鍵的數量,你可以使用像這樣的東西:
DELETE FROM my_table
WHERE ROWID IN
(SELECT ROWID
FROM my_table
START WITH (condition_on_the_row_that_you_want_to_delete)
CONNECT BY PRIOR (primary_key) = (self_foreign_key)
)
+1
這樣的解決方案的缺點是,插入的任何行會導致您的運行刪除的會話看不到仍然會被插入 - 並且成爲孤兒,因爲您已經殺死了父級,但子級行仍然被插入。 – 2015-01-19 18:37:26
相關問題
- 1. oracle刪除級聯條件
- 2. 級聯刪除
- 3. 級聯/刪除
- 4. 級聯刪除
- 5. Grails級聯刪除?
- 6. 級聯軟刪除
- 7. 級聯刪除mysql
- 8. MySql刪除級聯
- 9. MongoMapper +級聯刪除?
- 10. JPA級聯刪除
- 11. Yesod刪除級聯
- 12. LLBLGen級聯刪除?
- 13. SQL級聯刪除
- 14. NHibernate級聯刪除
- 15. 刪除級聯JayData
- 16. MySQL刪除級聯
- 17. JPA級聯刪除
- 18. MySQL - 刪除級聯
- 19. SQLite級聯刪除
- 20. Postgresql級聯刪除
- 21. 級聯刪除不與EF級聯
- 22. NHibernate,「在刪除級聯」,級聯刪除相關表中的行?
- 23. SQLite的刪除列和級聯刪除
- 24. JPA:級聯刪除不刪除子
- 25. 「級聯刪除」在mongoid
- 26. 刪除級聯招生
- 27. 配置級聯刪除
- 28. Coldfusion ORM:級聯刪除
- 29. Hibernate級聯刪除包
- 30. 級聯刪除SQL輸出
+ 1精彩解說Adam – 2011-12-20 19:35:38
那麼答案在哪裏?什麼更有效。 – magulla 2014-06-30 13:11:32
@magulla:與Oracle中的大多數事情一樣,這取決於。在執行刪除操作之前手動刪除多個子行可能會更有效,但是在發生這種情況時,並不會阻止另一個會話插入更多子級。考慮到如果子節點存在,Oracle會刪除每個刪除的父行,如果性能是最重要的,盡最大努力用單個語句刪除子表的相關行將是一條經驗法則,但「更好」的性能不能保證。 – 2015-02-10 15:07:12