先表明我的立场、我是绝对支持外键一定要加索引!
虽然在高版本的Oracle里、对这个要求有所降低、但依然有如下原因:
① 死锁
外键未加索引是导致死锁的最主要原因、因为
无论更新父表主键、或者删除一个父表记录、都会在子表加一个表锁
这就会不必要的锁定更多的行、从而影响并发性
② ON DELETE CASCADE
对于删除的每一个父行、都会把子表全表扫描一次
如:
EMP是DEPT的子表
DELETE dept WHERE deptno=10 会级联至EMP
③ 从父表查询子表
如:
EMP是DEPT的子表
SELECT *
FROM dept,emp
WHERE emp.deptno=dept.deptno and
dept.dname= :X
另外、证明子表由于外键未加索引而被锁住、可经由下列方法:
ALTER TABLE <child table name> DISABLE TABLE LOCK;
那么、对父表的可能导致表锁的任何 UPDATE 或 DELETE 都会收到如下错误:
ERROR at line 1:
虽然在高版本的Oracle里、对这个要求有所降低、但依然有如下原因:
① 死锁
外键未加索引是导致死锁的最主要原因、因为
无论更新父表主键、或者删除一个父表记录、都会在子表加一个表锁
这就会不必要的锁定更多的行、从而影响并发性
② ON DELETE CASCADE
对于删除的每一个父行、都会把子表全表扫描一次
如:
EMP是DEPT的子表
DELETE dept WHERE deptno=10 会级联至EMP
③ 从父表查询子表
如:
EMP是DEPT的子表
SELECT *
FROM dept,emp
WHERE emp.deptno=dept.deptno and
dept.dname= :X
另外、证明子表由于外键未加索引而被锁住、可经由下列方法:
ALTER TABLE <child table name> DISABLE TABLE LOCK;
那么、对父表的可能导致表锁的任何 UPDATE 或 DELETE 都会收到如下错误:
ERROR at line 1:
ORA-00069: cannot acquire lock -- table locks disable for <child table name>
以下做个简单的外键未加索引的测试: