当前位置 主页 > 服务器问题 > win服务器问题汇总 >

    远程数据库的表超过20个索引的影响详细解析

    栏目:win服务器问题汇总 时间:2019-11-19 00:11

    昨天同事参加了一个研讨会,有提到一个案例。一个通过dblink查询远端数据库,原来查询很快,但是远端数据库增加了一个索引之后,查询一下子变慢了。

    经过分析,发现那个通过dblink的查询语句,查询远端数据库的时候,是走索引的,但是远端数据库添加索引之后,如果索引的个数超过20个,就会忽略第一个建立的索引,如果查询语句恰好用到了第一个建立的索引,被忽略之后,只能走Full Table Scan了。

    听了这个案例,我查了一下,在oracle官方文档中,关于Managing a Distributed Database有一段话:

    Several performance restrictions relate to access of remote objects:

    Remote views do not have statistical data.
    Queries on partitioned tables may not be optimized.
    No more than 20 indexes are considered for a remote table.
    No more than 20 columns are used for a composite index.

    说到,如果远程数据库使用超过20个索引,这些索引将不被考虑。这段话,在oracle 9i起的文档中就已经存在,一直到12.2还有。

    那么,超过20个索引,是新的索引被忽略了?还是老索引被忽略了?如何让被忽略的索引让oracle意识到?我们来测试一下。
    (本文基于12.1.0.2的远程库和12.2.0.1的本地库进行测试,如果对测试过程没兴趣的,可以直接拉到文末看“综上”部分)

    (一)初始化测试表:

    --创建远程表:
    DROP TABLE t_remote;
     CREATE TABLE t_remote (
    col01 NUMBER,
    col02 NUMBER,
    col03 VARCHAR2(50),
    col04 NUMBER,
    col05 NUMBER,
    col06 VARCHAR2(50),
    col07 NUMBER,
    col08 NUMBER,
    col09 VARCHAR2(50),
    col10 NUMBER,
    col11 NUMBER,
    col12 VARCHAR2(50),
    col13 NUMBER,
    col14 NUMBER,
    col15 VARCHAR2(50),
    col16 NUMBER,
    col17 NUMBER,
    col18 VARCHAR2(50),
    col19 NUMBER,
    col20 NUMBER,
    col21 VARCHAR2(50),
    col22 NUMBER,
    col23 NUMBER,
    col24 VARCHAR2(50),
    col25 NUMBER,
    col26 NUMBER,
    col27 VARCHAR2(50)
    );
    alter table t_remote modify (col01 not null);
    INSERT INTO t_remote
    SELECT
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*'),
    rownum, rownum, rpad('*',50,'*')
    FROM dual
    CONNECT BY level <= 10000;
    commit; 
    create unique index t_remote_i01_pk on t_remote (col01);
    alter table t_remote add (constraint t_remote_i01_pk primary key (col01) using index t_remote_i01_pk);
    create index t_remote_i02 on t_remote (col02);
    create index t_remote_i03 on t_remote (col03);
    create index t_remote_i04 on t_remote (col04);
    create index t_remote_i05 on t_remote (col05);
    create index t_remote_i06 on t_remote (col06);
    create index t_remote_i07 on t_remote (col07);
    create index t_remote_i08 on t_remote (col08);
    create index t_remote_i09 on t_remote (col09);
    create index t_remote_i10 on t_remote (col10);
    create index t_remote_i11 on t_remote (col11);
    create index t_remote_i12 on t_remote (col12);
    create index t_remote_i13 on t_remote (col13);
    create index t_remote_i14 on t_remote (col14);
    create index t_remote_i15 on t_remote (col15);
    create index t_remote_i16 on t_remote (col16);
    create index t_remote_i17 on t_remote (col17);
    create index t_remote_i18 on t_remote (col18);
    create index t_remote_i19 on t_remote (col19);
    create index t_remote_i20 on t_remote (col20);
     
    exec dbms_stats.gather_table_stats(user,'T_REMOTE');