现在我有 3表 表 a (id,code,其它字段) 
表 b (id,code,其它字段)
表c  (id,code,其它字段)现在在 a b  c三表中分别给 code 加上了索引create index a_idex on a(code) 像这个写的索引
下面是我要问的问题了 select a.* from a 
left join b on a.code=b.code
left join c on c.code=a.code发现只有c表走了索引select a.* from a 
left join c on c.code=a.code
left join b on a.code=b.code
发现只有b表走了索引
select * from a 
left join c on c.code=a.code
left join b on a.code=b.code
发现不走索引这是什么情况 如何让他们都走索引呢?
索引

解决方案 »

  1.   

    已经验证过   和你a,b,c这3个表的数据量,统计信息有关系。
    如果要走索引的话  可强制 /*+index(表,索引)*/
      

  2.   


    /*+index(表,索引)*/  这样不是注释吗?
      

  3.   

    你用左外连接,那就是要把左边表的所有数据都查询出来,走索引效率并不高,如果不用外连接,那倒是有可能走索引。
    select a.* from a 
    join b on a.code=b.code
    join c on c.code=a.code
      

  4.   

    楼上的说的应该不错,   /*+index(表,索引)*/   这个是让优化器选择指定的索引
      

  5.   

    CBO可能认为全表扫比索引成本低  强制让Oracle走索引效率未必高呀
      

  6.   

    我这执行的结果和你说的不一样,也许和表中数据有关。左连接时左表的所有记录将会返回,所有CBO选择不走索引,因为走索引效率反而低。可以加hint来强制使用索引,只是效率估计反而低。
      SQL> select a.* from a
      2  left join b on a.code=b.code
      3  left join c on c.code=a.code;        ID       CODE
    ---------- ----------
             1         10
             2         20
             3         30
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2010575168-----------------------------------------------------------------------------
    | Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |       |     3 |   156 |     5   (0)| 00:00:01 |
    |   1 |  NESTED LOOPS OUTER |       |     3 |   156 |     5   (0)| 00:00:01 |
    |   2 |   NESTED LOOPS OUTER|       |     3 |   117 |     4   (0)| 00:00:01 |
    |   3 |    TABLE ACCESS FULL| A     |     3 |    78 |     3   (0)| 00:00:01 |
    |*  4 |    INDEX RANGE SCAN | B_IDX |     1 |    13 |     1   (0)| 00:00:01 |
    |*  5 |   INDEX RANGE SCAN  | C_IDX |     1 |    13 |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------Predicate Information (identified by operation id):
    ---------------------------------------------------   4 - access("A"."CODE"="B"."CODE"(+))
       5 - access("C"."CODE"(+)="A"."CODE")Note
    -----
       - dynamic sampling used for this statement (level=2)SQL> select a.* from a
      2  left join c on c.code=a.code
      3  left join b on a.code=b.code;        ID       CODE
    ---------- ----------
             1         10
             2         20
             3         30
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3294154415-----------------------------------------------------------------------------
    | Id  | Operation           | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    -----------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |       |     3 |   156 |     5   (0)| 00:00:01 |
    |   1 |  NESTED LOOPS OUTER |       |     3 |   156 |     5   (0)| 00:00:01 |
    |   2 |   NESTED LOOPS OUTER|       |     3 |   117 |     4   (0)| 00:00:01 |
    |   3 |    TABLE ACCESS FULL| A     |     3 |    78 |     3   (0)| 00:00:01 |
    |*  4 |    INDEX RANGE SCAN | C_IDX |     1 |    13 |     1   (0)| 00:00:01 |
    |*  5 |   INDEX RANGE SCAN  | B_IDX |     1 |    13 |     1   (0)| 00:00:01 |
    -----------------------------------------------------------------------------Predicate Information (identified by operation id):
    ---------------------------------------------------   4 - access("C"."CODE"(+)="A"."CODE")
       5 - access("A"."CODE"="B"."CODE"(+))Note
    -----
       - dynamic sampling used for this statement (level=2)SQL> select * from a
      2  left join c on c.code=a.code
      3  left join b on a.code=b.code;        ID       CODE         ID       CODE         ID       CODE
    ---------- ---------- ---------- ---------- ---------- ----------
             1         10
             2         20                                2         20
             3         30          3         30          3         30
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 3001270149---------------------------------------------------------------------------------------
    | Id  | Operation                     | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT              |       |     3 |   234 |     5   (0)| 00:00:01 |
    |   1 |  NESTED LOOPS OUTER           |       |     3 |   234 |     5   (0)| 00:00:01 |
    |   2 |   NESTED LOOPS OUTER          |       |     3 |   156 |     4   (0)| 00:00:01 |
    |   3 |    TABLE ACCESS FULL          | A     |     3 |    78 |     3   (0)| 00:00:01 |
    |   4 |    TABLE ACCESS BY INDEX ROWID| C     |     1 |    26 |     1   (0)| 00:00:01 |
    |*  5 |     INDEX RANGE SCAN          | C_IDX |     1 |       |     1   (0)| 00:00:01 |
    |   6 |   TABLE ACCESS BY INDEX ROWID | B     |     1 |    26 |     1   (0)| 00:00:01 |
    |*  7 |    INDEX RANGE SCAN           | B_IDX |     1 |       |     1   (0)| 00:00:01 |
    ---------------------------------------------------------------------------------------Predicate Information (identified by operation id):
    ---------------------------------------------------   5 - access("C"."CODE"(+)="A"."CODE")
       7 - access("A"."CODE"="B"."CODE"(+))Note
    -----
       - dynamic sampling used for this statement (level=2)
      

  7.   

    应该和你表结构有关,可能因为你建的索引在表中效率很低,CBO自己选择全扫描,
      

  8.   

    这是hint,楼主看看相关章节吧
      

  9.   

    大概来说ORACLE是根据获取到已经采集过的信息(如表总数、各表涉及到列的值分布、系统的吞吐能力、查询出来的结果量等等)自行判断取用最优的计划。
    a表作为驱动表,把A表的数据和主要B、C表做外连接,主要做过数据采集,code列的值分布,ORACLE自行判断的。
    ---查看索引的惟一值和总数,看看索引字段的重复值多少
    select DISTINCT_KEYS,NUM_ROWS,CLUSTERING_FACTOR From user_ind_statistics a where a.index_name = '索引名称';建议以下查询出来的数量比较一下,
    select count(*) from b ,a where a.code = b.code;
    select count(*) from b; 
    ---------
    select count(*) from c,a where a.code = b.code;
    select count(*) from c;
    若以上结果量差异相对小,或许ORACLE会走全表扫描
      

  10.   

    楼上说的对,Oracle数据库中,对于CBO优化器模式,查询数据时访问路径是否采用扫描索引的方式,主要看以下几个方面:表的总数据量、查询结果数据量占总数据量的比例、查询条件列(即索引列)的列值分布情况及是否创建了列直方图、系统的吞吐能力等。