Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Oracle外键执行计划?_Oracle_Oracle10g_Foreign Keys_Sql Execution Plan - Fatal编程技术网

Oracle外键执行计划?

Oracle外键执行计划?,oracle,oracle10g,foreign-keys,sql-execution-plan,Oracle,Oracle10g,Foreign Keys,Sql Execution Plan,考虑以下(过于简单的)情况: 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\u ID上没有索引,因此修改/删除PARENT非

考虑以下(过于简单的)情况:

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\u ID
上没有索引,因此修改/删除
PARENT
非常昂贵(Oracle需要对
CHILD
执行完整的表扫描以强制执行引用完整性)。然而,以下语句的执行计划

DELETE FROM PARENT WHERE PARENT_ID = 1
…不显示表格扫描(SYS_C0070229是父项上的索引。父项ID):

我知道有很多方法可以解决这个问题,但如果能“警告”查询执行计划本身的潜在问题(顺便说一句,MS SQL Server和其他数据库可能会这样做),那就更好了

这在甲骨文中可能吗


如果有必要的话,我正在使用Oracle 10.2。

强制引用完整性的查询是“递归sql”(即由Oracle生成),因此不会显示在解释计划中。如果您实际执行并跟踪该操作,您也将看到递归sql。

我已更改您的约束,添加“ON DELETE CASCADE”,否则Oracle将引发错误。(违反外键的默认值为DELETE restrict)

我相信您的问题的答案是“否”,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)'

有用的链接:

我不确定您是否有权访问此链接,但Oracle SQL Analyze()具有一些强大的SQL分析和调优功能。@ZackMacomber谢谢,我不熟悉它,但我会确保我了解它。它真的会按照我的要求执行吗?
设置自动跟踪启用
仍然显示相同的执行计划。要查看这个“递归SQL”,我应该做些什么特别的事情吗?@Branko-要查看递归SQL,您需要在会话上运行跟踪。