先表明我的立场、我是绝对支持外键一定要加索引!

虽然在高版本的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 DISABLE TABLE LOCK;

那么、对父表的可能导致表锁的任何 UPDATE 或 DELETE 都会收到如下错误:

ERROR at line 1:

ORA-00069: cannot acquire lock -- table locks disable for

以下做个简单的外键未加索引的测试:

建立表:

hr@ORCL> create table t_father (id number,name varchar2(25),primary key(id));

hr@ORCL> create table t_sun (fid number,name varchar2(25),foreign key(fid) references t_father(id));

hr@ORCL> select table_name,CONSTRAINT_NAME,STATUS,R_CONSTRAINT_NAME from user_constraints where owner=\'HR\' and table_name in (\'T_FATHER\',\'T_SUN\');

TABLE_NAME CONSTRAINT_NAME STATUS R_CONSTRAINT_NAME

------------------------------ ------------------------------ -------- ------------------------------

T_FATHER SYS_C005495 ENABLED

T_SUN SYS_C005497 ENABLED SYS_C005495

倒入数据并分析表:

hr@ORCL> insert into t_father select rownum,rownum||\'a\' from dual connect by rownum<1000;

hr@ORCL> insert into t_sun select rownum,rownum||\'b\' from dual connect by rownum<1000;

hr@ORCL> commit;

hr@ORCL> exec dbms_stats.gather_table_stats(ownname=>\'HR\',tabname=>\'T_FATHER\');

hr@ORCL> exec dbms_stats.gather_table_stats(ownname=>\'HR\',tabname=>\'T_SUN\');

用以下 TOM 给出的脚本检查外键无索引的表:

COLUMN COLUMNS format a30 word_wrapped

COLUMN tablename format a15 word_wrapped

COLUMN constraint_name format a15 word_wrapped

SELECT TABLE_NAME,

CONSTRAINT_NAME,

CNAME1 || NVL2(CNAME2, \',\' || CNAME2, NULL) ||

NVL2(CNAME3, \',\' || CNAME3, NULL) ||

NVL2(CNAME4, \',\' || CNAME4, NULL) ||

NVL2(CNAME5, \',\' || CNAME5, NULL) ||

NVL2(CNAME6, \',\' || CNAME6, NULL) ||

NVL2(CNAME7, \',\' || CNAME7, NULL) ||

NVL2(CNAME8, \',\' || CNAME8, NULL) COLUMNS

FROM (SELECT B.TABLE_NAME,

B.CONSTRAINT_NAME,

MAX(DECODE(POSITION, 1, COLUMN_NAME, NULL)) CNAME1,

MAX(DECODE(POSITION, 2, COLUMN_NAME, NULL)) CNAME2,

MAX(DECODE(POSITION, 3, COLUMN_NAME, NULL)) CNAME3,

MAX(DECODE(POSITION, 4, COLUMN_NAME, NULL)) CNAME4,

MAX(DECODE(POSITION, 5, COLUMN_NAME, NULL)) CNAME5,

MAX(DECODE(POSITION, 6, COLUMN_NAME, NULL)) CNAME6,

MAX(DECODE(POSITION, 7, COLUMN_NAME, NULL)) CNAME7,

MAX(DECODE(POSITION, 8, COLUMN_NAME, NULL)) CNAME8,

COUNT(*) COL_CNT

FROM (SELECT SUBSTR(TABLE_NAME, 1, 30) TABLE_NAME,

SUBSTR(CONSTRAINT_NAME, 1, 30) CONSTRAINT_NAME,

SUBSTR(COLUMN_NAME, 1, 30) COLUMN_NAME,

POSITION

FROM USER_CONS_COLUMNS) A,

USER_CONSTRAINTS B

WHERE A.CONSTRAINT_NAME = B.CONSTRAINT_NAME

AND B.CONSTRAINT_TYPE = \'R\'

GROUP BY B.TABLE_NAME, B.CONSTRAINT_NAME) CONS

WHERE COL_CNT > ALL

(SELECT COUNT(*)

FROM USER_IND_COLUMNS I

WHERE I.TABLE_NAME = CONS.TABLE_NAME

AND I.COLUMN_NAME IN (CNAME1, CNAME2, CNAME3, CNAME4, CNAME5,

CNAME6, CNAME7, CNAME8)

AND I.COLUMN_POSITION <= CONS.COL_CNT

GROUP BY I.INDEX_NAME)

/

hr@ORCL> /

TABLE_NAME CONSTRAINT_NAME COLUMNS

------------------------------ --------------- ------------------------------

T_SUN SYS_C005497 FID

以下进行测试:

1)Session_A:

hr@ORCL> select sid from v$session where sid in (select sid from v$mystat where rownum=1);

SID

----------

159

hr@ORCL> delete t_sun where fid=998;

1 row deleted.

2)Session_B:

hr@ORCL> select sid from v$session where sid in (select sid from v$mystat where rownum=1);

SID

----------

142

hr@ORCL> delete t_sun where fid=123;

1 row deleted.

3)Session_A:

hr@ORCL> delete t_father where id=555;

----请求子表的表锁却不可得之、被hang住了

用下面脚本查询数据库锁情况:

SELECT a.sid ||

decode(request,

0,

\' :holder\',\' :Waiter\') sess_id,blocking_session blocker,

lmode,

request,

a.type,

c.object_name,

decode(row_wait_obj#,

-1,

\'Holder of Lock !!!\',

dbms_rowid.rowid_create(1,

row_wait_obj#,

row_wait_file#,

row_wait_block#,

row_wait_row#)) row_id,

nvl(SQL_FULLTEXT, \'Holder of Lock !!!\') sqltext

FROM V$LOCK A, V$LOCKED_OBJECT B, ALL_OBJECTS C, V$SESSION D, V$SQL E

WHERE (id1, id2, a.type) in

(select id1, id2, type from v$lock where request > 0)

AND a.sid = b.session_id

AND b.object_id = c.object_id

AND d.sid = a.sid

AND d.sql_hash_value = e.hash_value(+)

sys@ORCL> /

SESS_ID BLOCKER LMODE REQUEST TY OBJECT_NAME ROW_ID SQLTEXT

------------------------------------------------ ---------- ---------- ---------- -- ------------------------------ ------------------ --------------------------------------------------------------------------------

159 :Waiter 142 3 5 TM T_SUN Holder of Lock !!! delete t_father where id=555

159 :Waiter 142 3 5 TM T_FATHER Holder of Lock !!! delete t_father where id=555

142 :holder 3 0 TM T_SUN Holder of Lock !!! Holder of Lock !!!

142 :holder 3 0 TM T_FATHER Holder of Lock !!! Holder of Lock !!!

By David Lin

2013-06-07

Good Luck

oracle外键有什么用,深入理解Oracle索引(20):外键是否应该加索引相关推荐

  1. oracle监听显示未成功_理解 oracle 的 lsnrctl status

    理解 oracle 的 "lsnrctl status" 先看看 lsnrctl status 的输出信息: Services Summary... Service "P ...

  2. oracle_sqlserver和mysql获取表外键的方法_mysql、sqlserver、oracle三种数据库维护索引、外键、字段语法总结...

    mysql.sqlserver.oracle三种数据库维护索引.外键.字段语法总结 1.     MYSQL数据库 1)    创建索引 CREATE INDEX index_name ON tabl ...

  3. oracle 建立外键 引用条件约束 不能添加,Oracle外键约束

    一.创建外键约束 两种方法 1.创建表时 create table 子表( id number, name varchar2(5), foreign key(id) references 父表(列名) ...

  4. 深入理解Oracle RAC 12c 笔记

    深入理解Oracle RAC 12c 跳转至: 导航. 搜索 文件夹 1 概述 2 集群件管理和故障诊断 3 执行实践 4 新特性 5 存储和ASM 6 应用设计上的问题 7 管理和调优一个复杂的RA ...

  5. 《深入理解Oracle 12c数据库管理(第二版)》PDF

    一:下载获取位置: 二:本书图样: 三:本书目录: 图书目录: 第1章 安装Oracle 1.1 了解OFA 1.1.1 Oracle清单目录 1.1.2 Oracle基础目录 1.1.3 Oracl ...

  6. 深入理解Oracle的并行操作

    并行(Parallel)和OLAP系统  并行的实现机制是:首先,Oracle会创建一个进程用于协调并行服务进程之间的信息传递,这个协调进程将需要操作的数据集(比如表的数据块)分割成很多部分,称为并行 ...

  7. 深入理解Oracle的并行操作【好文认真读】

    请尊重原文作者,http://czmmiao.iteye.com/blog/1487568 ------------------------------------------------------ ...

  8. oracle 主键_mysql 组合索引带主键ID的问题

    场景: mysql 5.7 某表 t_apply_info 上的2个索引,一个组合索引带了 主键字段 ID,另一个是同字段的单列索引 例如: KEY idx_1 (apply_serial_no,id ...

  9. sql语句的内连接、左外连接、右外连接的理解

    sql语句 内连接.左外连接.右外连接的理解 大家在初学数据库时,对DQL中的连接查询是否有些疑惑,不知道什么时候什么场景下该用那种连接查询? 不要着急,接下来由我来给大家介绍一下,本人对内连接.左外 ...

最新文章

  1. ubuntu 启动器
  2. 从源码安装GDB-8.1
  3. JDK版本不匹配...
  4. 中文自然语言处理(NLP)(三)运用python jieba模块计算知识点当中关键词的词频
  5. C++ 普通函数与函数模板 区别以及调用规则01
  6. Leetcode每日一题:80.remove-duplicates-from-sorted-array-ii(删除排序数组中的重复项Ⅱ)
  7. OC中的@的作用研究
  8. 台式计算机文件打不开怎么回事,电脑文件打不开怎么回事
  9. html的九宫格构图教学视频,构图的基本技巧之九宫格构图
  10. 罗永浩如果倒过来过,也很励志
  11. win中q-dir,everything,Windows Tabs,Clover各种效率神器(搜索,资源管理器,多标签)
  12. 微信小游戏接入遇到的坑
  13. 笔记本电脑触摸板无法使用(失灵)解决方案 (win10和win7通用)
  14. linux串口操作及设置
  15. 1553B总线基础知识及扩展
  16. [RelativeNAS] Relative Neural Architecture Search via Slow-Fast Learning
  17. 计算机一级office考试攻略,计算机一级考试MSOffice应试技巧
  18. IDEA 查找某个 jar 包是如何被引入的
  19. 安装画图工具kolourpaint
  20. 【环境搭建】WAMP环境+DVWA漏洞测试平台搭建过程

热门文章

  1. jedispool redis哨兵_Redis详解(九)------ 哨兵(Sentinel)模式详解
  2. C#命名空间namespace中不能直接包含字段(变量)或方法(函数)之类的成员
  3. 上海工程技术大学c语言,上海工程技术大学 C语言实习报告.doc
  4. python怎么创建变量_python怎么创建变量
  5. 六西格玛dfss_六西格玛系列知识之二:六西格玛管理的基本原理
  6. rapidxml在qt linux(gcc)下写xml文件出错
  7. MFC之CAsyncSocket详解
  8. 矩阵运算——平移,旋转,缩放
  9. TI Sitara AM335x系统之AM335x uboot spl分析
  10. java构建内存池队列_内存池完整实现代码及一些思考