• 技术文章 >数据库 >mysql教程

    Oracle外键列上是否需要索引?

    2016-06-07 16:53:56原创430

    外键列上缺少索引会带来两个问题,限制并发性、影响性能。而这两个问题中的任意一个都可能会造成严重性能问题。 无论是Or

    外键列上缺少索引会带来两个问题,限制并发性、影响性能。而这两个问题中的任意一个都可能会造成严重性能问题。

    无论是Oracle的官方文档,还是在Tom的书中都说明了两种情况下可以忽略外键上的索引。其实我认为不需要那么麻烦,与增加一个索引所带来的性能开销和磁盘空间开销相比,,确实索引可能引发的问题要严重得多。因此,我会选择在所有的外键列上添加索引,虽然可能导致创建了部分多余的索引,但是这样相除了外键约束由于确实索引所带来的性能问题和并发性问题。

    如果外键列上缺少索引,从主表关联子表的查询就只能对子表选择全表扫描的查询,这是显而易见的问题:

    SQL> CREATE TABLE T_P (ID NUMBER, NAME VARCHAR2(30));

    表已创建。

    SQL> ALTER TABLE T_P ADD PRIMARY KEY (ID);

    表已更改。

    SQL> CREATE TABLE T_C (ID NUMBER, FID NUMBER, NAME VARCHAR2(30));

    表已创建。

    SQL> ALTER TABLE T_C ADD CONSTRAINT FK_T_C
    2 FOREIGN KEY (FID)
    3 REFERENCES T_P (ID);

    表已更改。

    SQL> INSERT INTO T_P SELECT ROWNUM, TABLE_NAME FROM ALL_TABLES;

    已创建884行。

    SQL> INSERT INTO T_C SELECT ROWNUM, MOD(ROWNUM, 884) + 1, OBJECT_NAME
    2 FROM ALL_OBJECTS;

    已创建30339行。

    SQL> COMMIT;

    提交完成。

    SQL> SELECT A.ID, A.NAME, B.NAME
    2 FROM T_P A, T_C B
    3 WHERE A.ID = B.FID
    4 AND A.ID = 880;

    ID NAME NAME
    ---------- ------------------------------ ------------------------------
    880 T_COMPRESS /eb2b6b5_Options1
    880 T_COMPRESS DATE
    880 T_COMPRESS DEF$_SCHEDULE
    880 T_COMPRESS GV_$SESSION_EVENT
    .
    .
    .
    880 T_COMPRESS sun/io/ByteToCharCp1251
    880 T_COMPRESS /5ba3839f_DirStateFactoryResul
    880 T_COMPRESS USER_INDEXTYPES

    已选择34行。

    执行计划
    ----------------------------------------------------------
    0 SELECT STATEMENT Optimizer=CHOOSE
    1 0 MERGE JOIN
    2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_P'
    3 2 INDEX (UNIQUE SCAN) OF 'SYS_C002964' (UNIQUE)
    4 1 FILTER
    5 4 TABLE ACCESS (FULL) OF 'T_C'


    统计信息
    ----------------------------------------------------------
    0 recursive calls
    0 db block gets
    190 consistent gets
    0 physical reads
    0 redo size
    1829 bytes sent via SQL*Net to client
    394 bytes received via SQL*Net from client
    4 SQL*Net roundtrips to/from client
    0 sorts (memory)
    0 sorts (disk)
    34 rows processed


    由于缺少索引,上面的这个关联查询只能采用MERGE JOIN,而如果联立了外键列上的索引:

    SQL> CREATE INDEX IND_T_C_FID ON T_C (FID);

    索引已创建。

    SQL> SELECT A.ID, A.NAME, B.NAME
    2 FROM T_P A, T_C B
    3 WHERE A.ID = B.FID
    4 AND A.ID = 880;

    ID NAME NAME
    ---------- ------------------------------ ------------------------------
    880 T_COMPRESS /e1538703_EntryInfoImpl
    880 T_COMPRESS /7b832daf_ObjectStreamClassCom
    880 T_COMPRESS java/awt/peer/ScrollbarPeer
    880 T_COMPRESS /1982bd95_PermissionsEnumerato
    .
    .
    .
    880 T_COMPRESS /9ebda46b_GetInterface
    880 T_COMPRESS /c71f85e7_DefaultPopupFactory
    880 T_COMPRESS /7b549d81_DataFormatException

    已选择34行。

    执行计划
    ----------------------------------------------------------
    0 SELECT STATEMENT Optimizer=CHOOSE
    1 0 NESTED LOOPS
    2 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_P'
    3 2 INDEX (UNIQUE SCAN) OF 'SYS_C002964' (UNIQUE)
    4 1 TABLE ACCESS (BY INDEX ROWID) OF 'T_C'
    5 4 INDEX (RANGE SCAN) OF 'IND_T_C_FID' (NON-UNIQUE)


    统计信息
    ----------------------------------------------------------
    0 recursive calls
    0 db block gets
    42 consistent gets
    1 physical reads
    0 redo size
    1829 bytes sent via SQL*Net to client
    394 bytes received via SQL*Net from client
    4 SQL*Net roundtrips to/from client
    0 sorts (memory)
    0 sorts (disk)
    34 rows processed

    linux

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    上一篇:MySQL由于server-id相同造成的同步失败恢复 下一篇:Linux下C语言处理MySQL数据库示例程序
    千万级数据并发解决方案

    相关文章推荐

    • 图文详解mysql架构原理• mysql怎么判断是否是数字类型• mysql怎样查询数据出现的次数• mysql怎么删除唯一索引• Mysql怎么查询日志路径
    1/1

    PHP中文网