在oracle中,如果外键未加索引,对父表的修改,会导致子表被加上全表锁。这包括两种情况:

1.删除父表中的行,如果外键上没有索引,会导致子表被加上全表锁

2.更新父表的主键(根据关系数据库的原则,更新主键是一个巨大的”禁忌”,所以一般不会出现这种情况),如果外键上没有索引,会导致子表被加上全表锁

虽然,在Oracle9i及以上的版本中,这些全表锁都是短期的,他们仅在DML操作期间存在,而不是在整个事务的期间都存在。但是即使如此,这些全表锁还是可能(而且确实会)导致很严重的锁定问题。

可以通过如下语句,查询是否存在未加索引的外键:

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)

这个脚本将最多处理8列外键约束(如果你的外键有更多的列,可能就得重新考虑一下你的设计了)!

除了全表锁外,在以下情况下,未加索引的外键也可能带来问题:

     1.如果有on delete cascade,而且没有对子表加索引:例如,emp是dept的子表,delete deptno=10应该cascade(级联)至emp。如果emp中的deptno没有索引,那么删除dept表中的每一行时都会对emp做一次全表扫描。这个全表扫描可能是不必要的,而且如果从父表删除多行,父表中每删除一行就要扫描仪一次子表。

2.从父表查询子表:在此考虑emp/dept例子。利用deptno查询emp表是相当常见的。如果频繁地运行以下查询,你就会发现没有索引会使查询速度变慢:

select *
from dept, emp
where emp.deptno=dept.deptno
and dept.deptno=:x;

所以,要特表注意是否需要对外键加索引,防止出现这种Oracle“过分地锁定了”数据的情况。

 

                                                                                                                                                        --参考自《Oracle专家高级编程》

ORACLE外键和锁的更多相关文章

  1. Oracle外键不加索引会引起死锁问题

    转载链接:http://www.jb51.net/article/50161.htm 这篇文章主要介绍了Oracle外键不加索引引起死锁的情况及解决,需要的朋友可以参考下 --创建一个表,此表作为子表 ...

  2. Oracle外键(Foreign Key)使用详细的说明(一)

    Oracle外键(Foreign Key)使用详细的说明(一) 1.目标 演示如何Oracle使用外键数据库 2.什么是外键? 1)在Oracle数据库中,外键是用来实现參照完整性的方法之中的一个.打 ...

  3. 关于 Oracle外键列上是否需要索引问题?

    外键列上缺少索引会带来两个问题,限制并发性.影响性能.而这两个问题中的任意一个都可能会造成严重性能问题.   无论是Oracle的官方文档,还是在Tom的书中都说明了两种情况下可以忽略外键上的索引.其 ...

  4. Oracle外键需要建索引吗?

    关于Oracle中的外键,首先要说明一下. 1. 除非已定义了父表主键或唯一键约束,否则oracle将不允许创建子表的外键约束. 2. 在定义外键约束时,oracle不会自动创建索引,所以必须手动在与 ...

  5. Oracle 外键约束

    本文讨论一下Oracle中的外键约束问题,以及和DB2中的小不同. 首先创建测试环境. -- 创建测试主表. ID 是主键. CREATE TABLE test_main ( id INT, valu ...

  6. Oracle 外键级联更新

    Oracle数据库中,外键约束只允许级联删除,不允许级联更新,因此,如果想要实现主表数据更新后,子表外键自动更新,只能取消外键关系,通过前端程序来维护实现完整引用,一个代替的解决方案是使用延迟约束和触 ...

  7. mysql外键,锁

    mysql外键: 场景:用于建立两个表之间的联系,让A表中一个字段,可以在另一个表中字段值的范围去查找 注意事项: (1)被参照表和参照表字段属性必须一致 (2)参照表必须设置主键 (3)必须选择支持 ...

  8. 再一次强调,ORACLE外键必须加索引

    外键加索引是常识,必须牢记.本来不想写这样的简单案例.可是连续遇到好几起外键不加索引导致性能问题,所以还是写一下. 一个兄弟问我 delete from Sa_Sales_Comm_Detail s  ...

  9. Oracle 外键约束子表、父表

    CREATE TABLE employees(     employee_id      NUMBER(6),     last_name        VARCHAR2(25) NOT NULL, ...

随机推荐

  1. Python文件处理之文件指针(四)

    当我们读取文件内容时,并不能重复的读取,比如一个blogCblog.txt文件里有blogCblog内容,用两个read()方法读取blogCblog.txt的内容,会发现,第一个返回文件内容,第二个 ...

  2. Spring事务管理中@Transactional的propagation参数

    所谓事务传播性,就是被调用者的事务与调用者的事务之间的关系.举例说明. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 //in A.java Class A {     @Tr ...

  3. codeforces 235 B. Let's Play Osu!

    You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. F ...

  4. 运行Capture.exe找不到cdn_sfl401as.dll

    今天运行capture Orcad16.6显示缺少cdn_sfl401as.dll,昨天运行时并没有发现这种情况,回想今天安装了modelsim之后才发生这种情况,于是将modelsim卸载掉,再次启 ...

  5. Black Box

    http://poj.org/problem?id=1442 #include<cstdio> #include<algorithm> #include<queue> ...

  6. poj 3026Borg Maze

    http://poj.org/problem?id=3026 #include<cstdio> #include<iostream> #include<cstring&g ...

  7. C++编程中对缓冲区的理解(OS默认4096大小的缓冲区,有例子,很形象)

    什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区.缓冲区根据其对应的是输入设备还是输出 ...

  8. BZOJ2442: [Usaco2011 Open]修剪草坪

    2442: [Usaco2011 Open]修剪草坪 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 500  Solved: 244[Submit][ ...

  9. 设计模式(五):PROTOTYPE原型模式 -- 创建型模式

    1.定义 用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象. 2.适用场景 原型模式的主要思想是基于现有的对象克隆一个新的对象出来,一般是有对象的内部提供克隆的方法,通过该方法返回一个对 ...

  10. baiduMap 显示所有的marker(在视野里显示所有的)

    搞Android的,所以比较幸苦和累现在搞的app是关于百度地图的,因为要求要把所有覆盖物显示在一个视野...所以在网上找了很久,终于找打了方法 我引用的包是: 记录一下,其实不算很难.一个小点.翻了 ...