【问题标题】:Oracle cascade deleteOracle级联删除
【发布时间】:2011-12-20 06:43:58
【问题描述】:

表上的级联删除是否比单个删除语句(在单个 plsql 块中执行)更有效?

【问题讨论】:

    标签: sql oracle plsql


    【解决方案1】:

    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 针对 CHILD 为它在 PARENT 中删除的每条记录发出删除语句。

    一个不同的问题是两者中哪一个更有效:

    DELETE FROM CHILD WHERE PARENT_ID = 1;
    DELETE FROM PARENT WHERE PARENT_ID = 1;
    

    DELETE FROM PARENT WHERE PARENT_ID = 1;
    

    两者都启用了on delete cascade。令人惊讶的是,在上述第一种情况下,Oracle 将探测子表上的外键索引,以查看是否存在需要级联的行。如果不存在行,Oracle 不会执行级联删除。

    【讨论】:

    • 那么答案在哪里?什么更有效。
    • @magulla:与 Oracle 中的大多数东西一样,这取决于。在删除之前手动删除许多子行可能更有效,但没有什么能阻止另一个会话在此过程中插入更多子行。考虑到如果存在子表,Oracle 会为删除的每个父行发出删除操作,如果性能至关重要,那么您最好用一条语句删除子表感兴趣的行将是一个经验法则,但不能保证“更好”的性能.
    【解决方案2】:

    你不能像这样比较这两个选项。这不是性能问题,而是更多的设计和结构问题。

    如果您使用主键/外键设计数据库,则使用级联删除比手动搜索在哪个列和表上有外键并生成匹配的 SQL 语句更容易。

    cascading-deletes 功能的主要优点是它允许您减少执行删除操作所需的 SQL 语句数量

    【讨论】:

      【解决方案3】:

      如果你想级联删除并且没有定义外键,你可以使用这样的东西:

      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)
           )
      

      【讨论】:

      • 这种解决方案的缺点是,运行删除的会话没有看到的任何插入的行仍将被插入 - 并且是孤立的,因为您已经杀死了父行,但子行仍然被插入。
      • @AdamMusch 你提到的场景有解决方案吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-24
      • 2011-06-29
      • 2010-10-05
      相关资源
      最近更新 更多