• 使用索引的误区之一:没有使用复合索引的前导列导致查询不使用索引


     

    使用索引的误区之一:没有使用复合索引的前导列导致查询不使用索引

    在oracle中,我们经常以为建立了索引,sql查询的时候就会如我们所希望的那样使用索引,事实上,oracle只会在一定条件下使用索引,这里我们总结数第一点:oracle会在条件中包含了前导列时使用索引,即查询条件中必须使用索引中的第一个列,请看下面的例子

    SQL> select * from tab;

     

    TNAME                          TABTYPE  CLUSTERID

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

    BONUS                          TABLE

    DEPT                           TABLE

    DUMMY                          TABLE

    EMP                            TABLE

    SALGRADE                       TABLE

     

    建立一个联合索引(注意复合索引的索引列顺序)

    SQL> create index emp_id1 on emp(empno,ename,deptno);

     

    Index created

     

    建立一个单键索引

    SQL> create index emp_id2 on emp(sal);

     

    Index created

     

     

    SQL> select table_name,index_name from user_indexes

      2  where table_name='EMP';

     

    TABLE_NAME                     INDEX_NAME

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

    EMP                            EMP_ID1

    EMP                            EMP_ID2

     

    SQL> SELECT * FROM USER_IND_COLUMNS

      2  /

     

    INDEX_NAME                     TABLE_NAME                     COLUMN_NAME                                                                      COLUMN_POSITION COLUMN_LENGTH CHAR_LENGTH DESCEND

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

    EMP_ID1                        EMP                            EMPNO                                                                                          1            22           0 ASC

    EMP_ID1                        EMP                            ENAME                                                                                          2            10          10 ASC

    EMP_ID1                        EMP                            DEPTNO                                                                                         3            22           0 ASC

    EMP_ID2                        EMP                            SAL                                                                                            1            22           0 ASC

     

    下面的查询由于没有使用到复合索引的前导列,所以没有使用索引

     select job, empno from emp where ename='RICH';

     

    PLAN_TABLE_OUTPUT

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

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

    | Id  | Operation            |  Name       | Rows  | Bytes | Cost  |

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

    |   0 | SELECT STATEMENT     |             |       |       |       |

    |*  1 |  TABLE ACCESS FULL   | EMP         |       |       |       |

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

    Predicate Information (identified by operation id):

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

       1 - filter("EMP"."ENAME"='RICH')

    Note: rule based optimization

     

    14 rows selected

     

     

    下面的查询也由于没有使用到复合索引的前导列,所以没有使用索引

    select job, empno from emp where deptno=30;

     

    PLAN_TABLE_OUTPUT

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

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

    | Id  | Operation            |  Name       | Rows  | Bytes | Cost  |

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

    |   0 | SELECT STATEMENT     |             |       |       |       |

    |*  1 |  TABLE ACCESS FULL   | EMP         |       |       |       |

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

    Predicate Information (identified by operation id):

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

       1 - filter("EMP"."DEPTNO"=30)

    Note: rule based optimization

     

    14 rows selected

     

     

     

    下面的查询使用了复合索引中的前导列,所以查询走索引了

    select job, empno from emp where empno=7777;

     

    PLAN_TABLE_OUTPUT

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

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

    | Id  | Operation                   |  Name       | Rows  | Bytes | Cost  |

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

    |   0 | SELECT STATEMENT            |             |       |       |       |

    |   1 |  TABLE ACCESS BY INDEX ROWID| EMP         |       |       |       |

    |*  2 |   INDEX RANGE SCAN          | EMP_ID1     |       |       |       |

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

    Predicate Information (identified by operation id):

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

       2 - access("EMP"."EMPNO"=7777)

    Note: rule based optimization

     

    15 rows selected

     

     

     

     

    下面的查询使用了复合索引中的第一列和第二列,所以查询走索引了

    select job, empno from emp where empno=7777 and ename='RICH';

     

    PLAN_TABLE_OUTPUT

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

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

    | Id  | Operation                   |  Name       | Rows  | Bytes | Cost  |

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

    |   0 | SELECT STATEMENT            |             |       |       |       |

    |   1 |  TABLE ACCESS BY INDEX ROWID| EMP         |       |       |       |

    |*  2 |   INDEX RANGE SCAN          | EMP_ID1     |       |       |       |

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

    Predicate Information (identified by operation id):

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

       2 - access("EMP"."EMPNO"=7777 AND "EMP"."ENAME"='RICH')

    Note: rule based optimization

     

    15 rows selected

     

     

     

    使用了复合索引的全部列,所以走索引了,另外由于选了了索引中没有包含的列(job),

    所以进行索引全表扫描得到满足条件的rowid后,还要到表中检索相应的行

    select job, empno from emp where empno=7777 and ename='RICH' and deptno=30;

     

    PLAN_TABLE_OUTPUT

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

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

    | Id  | Operation                   |  Name       | Rows  | Bytes | Cost  |

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

    |   0 | SELECT STATEMENT            |             |       |       |       |

    |   1 |  TABLE ACCESS BY INDEX ROWID| EMP         |       |       |       |

    |*  2 |   INDEX RANGE SCAN          | EMP_ID1     |       |       |       |

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

    Predicate Information (identified by operation id):

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

       2 - access("EMP"."EMPNO"=7777 AND "EMP"."ENAME"='RICH' AND "EMP"."DEP

                  TNO"=30)

    Note: rule based optimization

     

    16 rows selected

     

     

     

     

    使用了复合索引的全部列,所以走索引了,而且由于所有选择的列都包含在索引中,所以仅仅进行了索引范围扫描

    select empno from emp where empno=7777 and ename='RICH' and deptno=30;

     

    PLAN_TABLE_OUTPUT

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

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

    | Id  | Operation            |  Name       | Rows  | Bytes | Cost  |

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

    |   0 | SELECT STATEMENT     |             |       |       |       |

    |*  1 |  INDEX RANGE SCAN    | EMP_ID1     |       |       |       |

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

    Predicate Information (identified by operation id):

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

       1 - access("EMP"."EMPNO"=7777 AND "EMP"."ENAME"='RICH' AND "EM

                  P"."DEPTNO"=30)

    Note: rule based optimization

     

    15 rows selected

    作者:行走的贝壳

    来源贝壳笔记 (http://ronli.cnblogs.com)

  • 相关阅读:
    python的eval、exec函数使用总结
    sorted()&enumerate()
    递归
    作用域
    Python3 os.stat() 方法
    android 电容屏(一):电容屏基本原理篇
    Linux 2.6内核与Linux 3.0 的区别!
    struct device的成员变量bus_id到哪里去了?
    Linux内核中ioremap映射的透彻理解
    Android 通过串口模拟 模拟物理按键
  • 原文地址:https://www.cnblogs.com/ronli/p/2119264.html
Copyright © 2020-2023  润新知