在开发中碰到一个问题,有4张表进行连接查询,表之间都用索引做连接条件,但是执行起来只有一个连接是走索引的,其他都是全表扫描,很郁闷,求解。
例子:
表:A,B,C,D;
对应的索引:a1,b1,c1,d1
查询语句:
1> select * from A,B,C,D where  A.a1=B.b1 and B.b1=C.c1 and C.c1=D.d1 and D.d1>1;
2> select * from A,B,C,D where  A.a1=B.b1 and B.b1=C.c1 and C.c1=D.d1 and D.d1=1;SQL2很正常,都走索引,但是SQL1就比较奇怪,求达人解惑!另外,对SQL1这样的查询,怎么才能都用到索引?

解决方案 »

  1.   

    很明显,你D.dl>1筛选出的数据量大,OracleCBO优化器认为此种情况走全表扫描更好,因此选择了走全表扫面而没有走索引
    同理,D.dl=1 筛选出来的数据量就很小,因此才走索引
    这跟你数据量有关的 
      

  2.   


    --给你举个例子,此例子是Oracle执行计划里的一个例子:
    对于
       select * from emp where deptno = 10;
            这个查询来说,如果是使用基于规则的优化器,而且deptno列上有有效的索引,则会通过deptno列上的索引来访问emp表。在绝大多数情况下,这是比较高效的,但是在一些特殊情况下,使用索引访问也有比较低效的时候,现举例说明:
            1) emp表比较小,该表的数据只存放在几个数据块中。此时使用全表扫描比使用索引访问emp表反而要好。因为表比较小,极有可能数据全在内存中,所以此时做全表扫描是最快的。而如果使用索引扫描,需要先从索引中找到符合条件记录的rowid,然后再一一根据这些rowid从emp中将数据取出来,在这种条件下,效率就会比全表扫描的效率要差一些。        2) emp表比较大时,而且deptno = 10条件能查询出表中大部分的数据如(50%)。如该表共有4000万行数据,共放在有500000个数据块中,每个数据块为8k,则该表共有约4G,则这么多的数据不可能全放在内存中,绝大多数需要放在硬盘上。此时如果该查询通过索引查询,则是你梦魇的开始。db_file_multiblock_read_count参数的值200。如果采用全表扫描,则需要500000/db_file_multiblock_read_count=500000/200=2500次I/O。但是如果采用索引扫描,假设deptno列上的索引都已经cache到内存中,所以可以将访问索引的开销忽略不计。因为要读出4000万x 50% = 2000万数据,假设在读这2000万数据时,有99.9%的命中率,则还是需要2000万次I/O,比上面的全表扫描需要的2500次多多了,所以在这种情况下,用索引扫描反而性能会差很多。在这样的情况下,用全表扫描的时间是固定的,但是用索引扫描的时间会随着选出数据的增多使查询时间相应的延长。