2012-02-15 15 views
5

consideri il seguente (semplicistico) Posizione:Piano di esecuzione di chiavi esterne Oracle?

CREATE TABLE PARENT (
    PARENT_ID INT PRIMARY KEY 
); 

CREATE TABLE CHILD (
    CHILD_ID INT PRIMARY KEY, 
    PARENT_ID INT NOT NULL, 
    FOREIGN KEY (PARENT_ID) REFERENCES PARENT (PARENT_ID) 
); 

v'è alcun indice su CHILD.PARENT_ID, quindi modifica/cancellazione PARENT è costoso (Oracle deve fare una scansione completa della tabella su CHILD per applicare l'integrità referenziale). Eppure il piano di esecuzione per la seguente dichiarazione ...

DELETE FROM PARENT WHERE PARENT_ID = 1 

... non mostra la scansione di tabella (SYS_C0070229 è l'indice sul PARENT.PARENT_ID):

query plan

So che ci sono modi a see all unindexed FOREIGN KEYs, ma sarebbe ancora meglio se potessi essere "avvertito" di un potenziale problema nel piano di esecuzione della query stesso (BTW, MS SQL Server e probabilmente altri database farlo).

È possibile in Oracle?

Sto usando Oracle 10.2 se questo è importante.

+1

non sono sicuro se si ha accesso a questo o no, ma Oracle SQL Analyse (http://docs.oracle.com/html/A86647_01/vmqintro.htm) ha alcune potenti funzionalità per l'analisi e l'ottimizzazione di SQL. –

+0

@ZackMacomber Grazie, non ho familiarità con esso, ma farò in modo di imparare. Effettivamente farà ciò che ho chiesto? –

risposta

4

ho cambiato il tuo vincolo di aggiungere il "ON DELETE CASCADE", senza la quale Oracle genererà un errore. (L'impostazione predefinita per le violazioni di chiave esterna è cancellare limito)

Credo che la risposta alla tua domanda è "NO", Oracle non ti avvisa della colonna chiave esterna non indicizzata. In pratica, la maggior parte di tali colonne sono indicizzate, poiché questo è il modo in cui si unirebbe il genitore al figlio.

Se si vuole dimostrare a qualcuno che non ha un indice causerà problemi di blocco e escalation (qualcosa non molto desiderabile), si potrebbe semplicemente disabilitare il blocco della tabella e mostrare l'errore.

SQL> alter table child disable table lock; 

Table altered. 

SQL> delete from parent where parent_id = 10; 
delete from parent where parent_id = 10 
      * 
ERROR at line 1: 
ORA-00069: cannot acquire lock -- table locks disabled for CHILD 

E per la questione spiegare programma, come altri hanno fatto notare, la SQL per eliminare dalla tabella figlio è uno SQL ricorsiva e non è indicata nel piano di spiegare.

Se TRACCIA la sessione, vedrai l'SQL ricorsivo.

1* alter session set SQL_TRACE = TRUE 
SQL>/

Session altered. 

SQL> delete from parent where parent_id = 10; 

1 row deleted. 

SQL> commit; 

Commit complete. 

SQL> alter session set SQL_TRACE=FALSe; 

Session altered. 

===================== 
PARSING IN CURSOR #2 len=39 dep=0 uid=65 oct=7 lid=65 tim=763167901560 hv=3048246147 ad='3160891c' 
delete from parent where parent_id = 10 
END OF STMT 
PARSE #2:c=0,e=61,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=763167901555 
===================== 
PARSING IN CURSOR #1 len=48 dep=1 uid=0 oct=7 lid=0 tim=763167976106 hv=2120075951 ad='26722c20' 
delete from "RC"."CHILD" where "PARENT_ID" = :1 
END OF STMT 
PARSE #1:c=0,e=42,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=763167976100 
EXEC#1:c=0,e=291,p=0,cr=7,cu=7,mis=0,r=2,dep=1,og=4,tim=763168080347 
EXEC#2:c=0,e=130968,p=0,cr=8,cu=14,mis=0,r=1,dep=0,og=1,tim=763168091605 
STAT #2 id=1 cnt=1 pid=0 pos=1 obj=0 op='DELETE PARENT (cr=8 pr=0 pw=0 time=130887 us)' 
STAT #2 id=2 cnt=1 pid=1 pos=1 obj=58703 op='INDEX UNIQUE SCAN SYS_C006951 (cr=1 pr=0 pw=0 time=19 us)' 
STAT #1 id=1 cnt=0 pid=0 pos=1 obj=0 op='DELETE CHILD (cr=7 pr=0 pw=0 time=233 us)' 
STAT #1 id=2 cnt=2 pid=1 pos=1 obj=58704 op='TABLE ACCESS FULL CHILD (cr=7 pr=0 pw=0 time=76 us)' 

Link utili: http://www.oracle-base.com/articles/10g/SQLTrace10046TrcsessAndTkprof10g.php

2

La query per applicare l'integrità referenziale è "sql ricorsivo" (cioè generata da Oracle), pertanto non verrà visualizzata nel piano di spiegazione. Se esegui effettivamente l'operazione e la traccia, vedrai anche lo sql ricorsivo.

+0

"SET AUTOTRACE ON" mostra ancora lo stesso piano di esecuzione. C'è qualcosa di speciale che dovrei fare per vedere questo "SQL ricorsivo"? –

+0

@Branko: per vedere SQL ricorsivo, è necessario eseguire una traccia sulla sessione. –