2011-12-20 16 views
7

L'eliminazione a cascata su una tabella è più efficiente delle singole istruzioni di eliminazione (eseguite in un unico blocco plsql)?Elimina Oracle cascade

risposta

17

Ciò che cascade delete fa è emettere dichiarazioni di cancellazione individuali.

esaminare le seguenti test case:

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; 

Nel file di traccia, troverete una linea come questa:

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 

Questo è Oracle rilascio di una dichiarazione di eliminazione contro CHILD per ogni record è eliminazione in PARENT.

una questione diversa sarebbe quale delle due sono più efficienti:

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

vs

DELETE FROM PARENT WHERE PARENT_ID = 1; 

entrambi con on delete cascade abilitato. Sorprendentemente, nel primo caso sopra, Oracle controllerà l'indice della chiave esterna sulla tabella figlia per vedere se esistono delle righe che richiederebbero una cascata. Se non ci sono righe, Oracle non esegue l'eliminazione a cascata.

+0

+ 1 spiegazione superba Adam –

+1

quindi dov'è la risposta? cos'è più efficiente. – magulla

+0

@magulla: come con la maggior parte delle cose in Oracle, dipende. Potrebbe essere più efficiente cancellare manualmente molte righe figlio prima di fare l'eliminazione, ma nulla impedisce ad un'altra sessione di inserire più bambini mentre sta succedendo. Considerando che Oracle emette un'eliminazione per ogni riga genitore cancellata se esistono bambini, se la prestazione è fondamentale, fare del proprio meglio per eliminare le righe di interesse della tabella secondaria con una singola affermazione sarebbe una regola empirica, ma non è garantita una prestazione "migliore" . –

5

Non è possibile confrontare entrambe le opzioni come questa. non è un problema di prestazioni ma più design e struttura.

Se si progetta il database utilizzando chiavi primarie/esterne, sarà più facile eliminarlo utilizzando le eliminazioni in cascata anziché la ricerca manuale in cui si dispone di chiavi esterne su quale colonna e tabella e si generano istruzioni SQL di lavorazione.

Il vantaggio principale per la funzione in cascata elimina è che permette di ridurre la quantità di istruzioni SQL è necessario eseguire eliminare le azioni

0

Se si vuole eliminare in cascata e non hanno una chiave esterna definita , è possibile utilizzare qualcosa di simile:

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

Lo svantaggio di una soluzione di questo tipo sarebbe che tutte le righe inserite che la sessione in esecuzione dell'eliminazione non vede saranno ancora inserite e orfane, dato che hai ucciso il genitore, ma le righe secondarie vengono ancora inserite. –