2012-02-15 25 views
5

Considere lo siguiente (simplista) Situación:plan de ejecución de clave foránea de 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) 
); 

No hay índice en CHILD.PARENT_ID, por lo que modificar/borrar PARENT es caro (Oracle tiene que hacer un escaneo completo de tabla en CHILD para hacer cumplir la integridad referencial). Sin embargo, el plan de ejecución de la siguiente declaración ...

DELETE FROM PARENT WHERE PARENT_ID = 1 

... no muestra el recorrido de tabla (SYS_C0070229 es el índice en PARENT.PARENT_ID):

query plan

Sé que hay maneras a see all unindexed FOREIGN KEYs, pero sería aún mejor si pudiera ser "advertido" de un problema potencial en el plan de ejecución de la consulta en sí (BTW, MS SQL Server y posiblemente otras bases de datos hacen eso).

¿Es eso posible en Oracle?

Estoy usando Oracle 10.2 si eso es importante.

+1

no estoy seguro de si tiene acceso a esto o no, pero Oracle SQL Analizar (http://docs.oracle.com/html/A86647_01/vmqintro.htm) tiene algunas funciones potentes para el análisis y ajuste de SQL. –

+0

@ ZackMacomber Gracias, no estoy familiarizado pero me aseguraré de aprender. ¿Realmente hará lo que le pedí? –

Respuesta

4

he alterado su limitación para añadir el "ON DELETE CASCADE", sin la cual Oracle generará un error. (El valor predeterminado para violaciónes de clave externa es Eliminar restringir)

Creo que la respuesta a su pregunta es "NO", Oracle no le advierte sobre la columna clave extranjera no indexada. En la práctica, la mayoría de tales columnas están indexadas, ya que así es como se uniría el padre al hijo.

Si desea demostrar a alguien que no tener un índice causará problemas de bloqueo y escaladas (algo no muy deseable), simplemente podría desactivar el bloqueo de la tabla y mostrar el error.

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 

Y para la pregunta explicar el plan, como otros han señalado, el SQL para eliminar de la tabla secundaria es un SQL recursivo y no se muestra en el plan de explicar.

Si TRAZA la sesión, verá el SQL recursivo.

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

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

2

La consulta para forzar la integridad referencial es "sql recursivo" (es decir, generada por Oracle), por lo tanto no se mostrará en el plan de explicación. Si realmente lleva a cabo la operación y la rastrea, verá el sql recursivo también.

+0

El 'SET AUTOTRACE ON' todavía muestra el mismo plan de ejecución. ¿Hay algo especial que debería hacer para ver este "SQL recursivo"? –

+0

@Branko: para ver SQL recursivo, necesitaría ejecutar un seguimiento en la sesión. –

Cuestiones relacionadas