2012-02-15 1 views
5

Рассмотрим следующий (упрощенно) ситуацию:Внешний план выполнения внешнего ключа 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) 
); 

Там нет индекса на CHILD.PARENT_ID, поэтому изменение/удаление PARENT является дорогостоящим (Oracle должен сделать полное сканирование таблицы на CHILD для обеспечения ссылочной целостности). Тем не менее, план выполнения для следующего утверждения ...

DELETE FROM PARENT WHERE PARENT_ID = 1 

... не показывает сканирование таблицы (SYS_C0070229 является индекс PARENT.PARENT_ID):

query plan

Я знаю, что есть способы до see all unindexed FOREIGN KEYs, но было бы даже лучше, если бы я мог быть «предупрежден» о потенциальной проблеме самого плана выполнения запроса (BTW, MS SQL Server и, возможно, другие базы данных).

Возможно ли это в Oracle?

Я использую Oracle 10.2, если это имеет значение.

+1

Я не уверен, если у вас есть доступ к этому или нет, но Oracle SQL Analyze (http://docs.oracle.com/html/A86647_01/vmqintro.htm) имеет некоторые мощные функции для анализа и настройки SQL. –

+0

@ZackMacomber Спасибо, я не знаком с этим, но я обязательно узнаю. Будет ли это делать то, что я спросил? –

ответ

4

Я изменил свое ограничение, чтобы добавить «ON DELETE CASCADE», без которого Oracle выдаст ошибку. (По умолчанию для внешнего ключа нарушения, это удалить ограничения)

Я считаю, что ответ на ваш вопрос «НЕТ», Oracle не предупреждает вас о столбце неиндексированного внешнего ключа. На практике большинство таких столбцов индексируются, так как именно так вы будете присоединяться к родительскому объекту для ребенка.

Если вы хотите доказать кому-то, что отсутствие индекса приведет к проблемам блокировки и эскалации (что-то не очень желательно), вы можете просто отключить блокировку таблицы и показать ошибку.

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 

И для объяснения плана вопроса, как и другие указали, SQL, чтобы удалить из дочерней таблицы является рекурсивным SQL и не отображается в плане объяснения.

Если вы пройдете сеанс, вы увидите рекурсивный SQL.

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

Полезные ссылки: http://www.oracle-base.com/articles/10g/SQLTrace10046TrcsessAndTkprof10g.php

2

Запрос для обеспечения ссылочной целостности - это «рекурсивный sql» (т. Е. Сгенерированный Oracle), поэтому не будет отображаться в плане объяснения. Если вы действительно выполняете операцию и отслеживаете ее, вы также увидите рекурсивный sql.

+0

«SET AUTOTRACE ON» по-прежнему показывает тот же план выполнения. Есть ли что-то особенное, что я должен сделать, чтобы увидеть этот «рекурсивный SQL»? –

+0

@Branko - чтобы увидеть рекурсивный SQL, вам нужно запустить трассировку в сеансе. –

 Смежные вопросы

  • Нет связанных вопросов^_^