我这里有两张表: po_headers 和po_lines;
    表结构如下:
         create table po_headers(
            ph_id number,
            ph_segment varchar2(50)
            primary key(ph_id)   
         )
          /
        create table po_lines(
           pl_id number,
           ph_id number,
           pl_segment varchar2(50),
           pl_name varchar2(60)
           primary key(pl_id)
        ) 
         /
       其中po_headers表中主键列是唯一索引;
       po_lines表中除了主键外,还有一个唯一索引:
            create unique index line_seg_index on ets_flex_values(ph_id,pl_segment);
       这两张表中记录不是太多,其中po_lines表中大致有700条记录.
       我的数据库是9i,
       其中比较疑惑的是下面这条sql,po_headers走了索引,而对po_lines表的操作,没有走line_seg_index索引,而是走了全表扫描.
        select ph.*,pl.* from po_headers ph,po_lines pl
        where ph.ph_id = pl.ph_id and ph.ph_id = 340;
       而下面的这条语句会走索引:
        select ph.*,pl.ph_id,pl.pl_segment from po_headers ph,po_lines pl
        where ph.ph_id = pl.ph_id and ph.ph_id = 340;
      但如果在po_lines上创建下面的普通索引:
       create index line_seg_index on ets_flex_values(ph_id);
      则下面的sql会选择索引:
        select ph.*,pl.* from po_headers ph,po_lines pl
        where ph.ph_id = pl.ph_id and ph.ph_id = 340;
     那位大侠能详细讲解一下oracle的索引原理?
          
       
          

解决方案 »

  1.   

    索引还真不是一两句话能够将清楚的,推荐一本好书:
    Oracle 9i & 10g编程艺术:深入数据库体系结构

    里面讲解得非常详细
      

  2.   

    1、没有执行计划,只能从表面上看,
    第一个语句未使用po_lines上的索引原因是,由于数据量较少,
    全表扫描比使用索引和读取表数据块代价更低。2、第二句使用索引的原因是,从po_lines中查询出的列都
    出现在索引中,所以,只需要扫描索引就可以了,不需要读取表
    数据块。3、表连接执行计划主要有三种形式,NEST LOOP、HASH JOIN、
    MERGE JOIN具体使用那种,要看统计数据和执行计划。4、索引原理可以读一下TOM的ORACLE 9I/10g编程艺术
      

  3.   

    pl的现有的两个索引分别是针对pl.pl_id和pl.ph_id,pl.pl_segment
    这条语句:
    select ph.*,pl.* from po_headers ph,po_lines pl
      where ph.ph_id = pl.ph_id and ph.ph_id = 340;用不上索引,没有匹配的,即使是ets_flex_values(ph_id,pl_segment),使用索引的条件:
    查询字段数等于或包含索引字段,根据唯一索引,b*树的建立规则,复合索引字段ph_id,pl_segment是作为一个整体作为树中的节点,而不是先ph_id,然后pl_segment在ph_id节点的子节点这种方式。而你单独查pl.ph_id是不匹配b*树查找方式的。所以不会利用到索引。另外即使符合使用索引的条件,优化也会自己分析,是不是全表扫描来得更快。也不一定会使用索引。