ITPub博客

首页 > 数据库 > Oracle > 外键与索引

外键与索引

原创 Oracle 作者:jelephant 时间:2013-12-18 15:54:23 0 删除 编辑
当我们更新父表主键或者删除一个父记录时,都会在子表上加一个表锁,在这条语句完成之前,不允许对子表做任何修改,从而影响并发性。

外键未加索引,可能导致如下问题:
1、删除父表多行时,对于父表的每一行删除,都会把子表全表扫描一次
2、从父表查询子表时,没有索引查询很慢(这就是为什么内嵌表时,建议对隐藏列nested_column_id加索引)

查询操作:

JEL@JEL >create table t1 (id number primary key,name varchar2(20));

Table created.

JEL@JEL >create table t2 (id number,fid number references t1(id),name varchar2(20));

Table created.

JEL@JEL >insert into t1 select object_id,OBJECT_TYPE from all_objects;

9379 rows created.

JEL@JEL >insert into t2 select DATA_OBJECT_ID,object_id,OBJECT_TYPE from all_objects;

9379 rows created.

JEL@JEL >commit;

JEL@JEL >set autotrace on;
JEL@JEL >select f.id,f.name,c.name from t1 f,t2 c where f.id=c.fid and f.id=20;

        ID NAME                 NAME
---------- -------------------- --------------------
        20 TABLE                TABLE


Execution Plan
----------------------------------------------------------
Plan hash value: 3227500623

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

| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)
| Time     |

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

|   0 | SELECT STATEMENT             |             |     1 |    21 |    19   (0)
| 00:00:01 |

|   1 |  NESTED LOOPS                |             |     1 |    21 |    19   (0)
| 00:00:01 |

|   2 |   TABLE ACCESS BY INDEX ROWID| T1          |     1 |    10 |     2   (0)
| 00:00:01 |

|*  3 |    INDEX UNIQUE SCAN         | SYS_C002870 |     1 |       |     1   (0)
| 00:00:01 |

|*  4 |   TABLE ACCESS FULL          | T2          |     1 |    11 |    17   (0)
| 00:00:01 |

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


Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("F"."ID"=20)
   4 - filter("C"."FID"=20)


Statistics
----------------------------------------------------------
       1317  recursive calls
          0  db block gets
        267  consistent gets
          0  physical reads
          0  redo size
        525  bytes sent via SQL*Net to client
        380  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         17  sorts (memory)
          0  sorts (disk)
          1  rows processed


没有给子表创建索引,所以对t2表进行了全表扫描。

JEL@JEL >create index i_t2 on t2(fid);

Index created.

JEL@JEL >select f.id,f.name,c.name from t1 f,t2 c where f.id=c.fid and f.id=20;

        ID NAME                 NAME
---------- -------------------- --------------------
        20 TABLE                TABLE


Execution Plan
----------------------------------------------------------
Plan hash value: 4198376869

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

| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)
| Time     |

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

|   0 | SELECT STATEMENT             |             |     1 |    21 |     4   (0)
| 00:00:01 |

|   1 |  NESTED LOOPS                |             |     1 |    21 |     4   (0)
| 00:00:01 |

|   2 |   TABLE ACCESS BY INDEX ROWID| T1          |     1 |    10 |     2   (0)
| 00:00:01 |

|*  3 |    INDEX UNIQUE SCAN         | SYS_C002870 |     1 |       |     1   (0)
| 00:00:01 |

|   4 |   TABLE ACCESS BY INDEX ROWID| T2          |     1 |    11 |     2   (0)
| 00:00:01 |

|*  5 |    INDEX RANGE SCAN          | I_T2        |     1 |       |     1   (0)
| 00:00:01 |

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


Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("F"."ID"=20)
   5 - access("C"."FID"=20)


Statistics
----------------------------------------------------------
       1362  recursive calls
          0  db block gets
        224  consistent gets
          0  physical reads
          0  redo size
        525  bytes sent via SQL*Net to client
        380  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
         18  sorts (memory)
          0  sorts (disk)
          1  rows processed

利用了索引进行查找

删除操作:

会话一
JEL@JEL >select OWNER,INDEX_NAME,INDEX_TYPE from all_indexes where index_name='I_T2';

no rows selected

JEL@JEL >delete t2 where fid=20;

1 row deleted.

会话二
JEL@JEL >insert into t1 values (1,'T');

1 row created.

JEL@JEL >delete t1 where id=1;


会话二被锁定,无法操作

会话一执行rollback后,会话二完成删除


JEL@JEL >create index i_t2 on t2(fid);

Index created.

外键创建索引,重复以上操作,顺利完成。

以上可知,不管父表主键有没有变化,都会锁定子表

结论,外键需要加索引

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29337971/viewspace-1063601/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: null与索引
请登录后发表评论 登录
全部评论

注册时间:2013-12-07

  • 博文量
    143
  • 访问量
    681886