SQL查询语句如下:
select /*+ first_rows index(operator.pbetdetail,supagid_idx) */ * from operator.pbetdetail where supagid=64563 and agid=64569 and externparam='1546' and isrevocation=1;
数据库中有记录300多W行,其中supagid_idx是位图索引在supagid这个列上面,这个数据列上面的唯一值不超过50个,下面是执行计划,走索引,说明效果很好
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 108862010--------------------------------------------------------------------------------
------------| Id  | Operation                    | Name        | Rows  | Bytes | Cost (%CPU)
| Time     |--------------------------------------------------------------------------------
------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |             |     1 |   355 | 52872   (1)
| 00:10:35 ||*  1 |  TABLE ACCESS BY INDEX ROWID | PBETDETAIL  |     1 |   355 | 52872   (1)
| 00:10:35 ||   2 |   BITMAP CONVERSION TO ROWIDS|             |       |       |
|          ||*  3 |    BITMAP INDEX SINGLE VALUE | SUPAGID_IDX |       |       |
|          |PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------
------------
Predicate Information (identified by operation id):
---------------------------------------------------   1 - filter("EXTERNPARAM"='1546' AND "AGID"=64569 AND "ISREVOCATION"=1)
   3 - access("SUPAGID"=64563)
PLAN_TABLE_OUTPUT
改变后的SQL查询语句如下:
select /*+ first_rows index(operator.pbetdetail,supagid_idx) */ count(*) from operator.pbetdetail where supagid=64563 and agid=64569 and externparam='1546' and isrevocation=1;
执行计划如下PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1324743298--------------------------------------------------------------------------------
-| Id  | Operation          | Name       | Rows  | Bytes | Cost (%CPU)| Time
|--------------------------------------------------------------------------------
-
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |            |     1 |    15 | 32906   (2)| 00:06:35
||   1 |  SORT AGGREGATE    |            |     1 |    15 |            |
||*  2 |   TABLE ACCESS FULL| PBETDETAIL |     1 |    15 | 32906   (2)| 00:06:35
|--------------------------------------------------------------------------------
-PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------   2 - filter("EXTERNPARAM"='1546' AND "AGID"=64569 AND "SUPAGID"=64563
              AND "ISREVOCATION"=1)Note
-----
   - 'PLAN_TABLE' is old version这个时候就没有走索引了,用的是全表扫描,请问第二个怎么不走索引了,还有我将SQL语句改成
 select /*+ first_rows index(operator.pbetdetail,supagid_idx) */ count(*) from operator.pbetdetail where supagid=64563;
后面的限定条件不要了,又可以走索引了,执行计划如下
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 3400660245--------------------------------------------------------------------------------
-----------| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)|
 Time     |--------------------------------------------------------------------------------
-----------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |     1 |     5 |    46   (0)|
 00:00:01 ||   1 |  SORT AGGREGATE             |             |     1 |     5 |            |
          ||   2 |   BITMAP CONVERSION COUNT   |             |   253K|  1239K|    46   (0)|
 00:00:01 ||*  3 |    BITMAP INDEX SINGLE VALUE| SUPAGID_IDX |       |       |            |
          |PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------
Predicate Information (identified by operation id):
---------------------------------------------------   3 - access("SUPAGID"=64563)NotePLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
-----
   - 'PLAN_TABLE' is old version难道跟其他字段还有影响吗,其他字段只是额外的限定查询条件而已,他们上面是没有任何索引的,请教各位了,
我的select /*+ first_rows index(operator.pbetdetail,supagid_idx) */ count(*) from operator.pbetdetail where supagid=64563 and agid=64569 and externparam='1546' and isrevocation=1;语句该怎么写,才能让它走索引,这样提高查询效率呢????

解决方案 »

  1.   

    count(*) 改成count(supagid) 试试
      

  2.   

    oracle版本?分析一下表。oracle自己算的走索引比走全表扫描快
      

  3.   

    我用的是oracle 10g,count(*) 改成count(supagid)也试过了,一样是走全表扫描
      

  4.   


    SELECT /*+ parallel(PBETDETAIL,8) */
     *
      FROM OPERATOR.PBETDETAIL
     WHERE SUPAGID = 64563
       AND AGID = 64569
       AND EXTERNPARAM = '1546'
       AND ISREVOCATION = 1;
      

  5.   

    parallel提示只是提高了全表扫描的速度,我想知道为什么现在我不能用索引扫描,单独的一个查询条件是可以的,但是加了AGID ,EXTERNPARAM,ISREVOCATION 中的任何一个就不行了
      

  6.   

    把后面两个字段都建位图索引,使用and条件进行逻辑位运算应该这样才可以吧!
      

  7.   

    搞错了,跟AGID ,EXTERNPARAM,ISREVOCATION这几个字段是没有 关系的,主要是用了
    count(*)来计算有多少条记录的时候就不走索引了,如果用
    select /*+ first_rows index(operator.pbetdetail,supagid_idx) */ * from operator.pbetdetail where supagid=64563 and agid=64569 and externparam='1546' and isrevocation=1;是可以走索引的
      

  8.   

    analyze table pbetdetail compute statistics; 
    分析一下表试试
      

  9.   

    用不用索引,用哪个索引
    oracle是根据where条件来决定的
      

  10.   


    Oracle Optimizer CBO RBO
    http://blog.csdn.net/tianlesoftware/article/details/5824886从8i开始,Oracle 引入了CBO(Cost Based Optimizer),它的思路是让Oracle 获取所有执行计划相关的信息,通过对这些信息做计算分析,最后得出一个代价最小的执行计划作为最终的执行计划。
     
    CBO是一种比RBO 更理性化的优化器。从10g开始,Oracle 已经彻底丢弃了RBO。 即使在表,索引没有被分析的时候,Oracle依然会使用CBO。此时,Oracle 会使用一种叫做动态采样的技术,在分析SQL的时候,动态的收集表,索引上的一些数据块,使用这些数据块的信息及字典表中关于这些对象的信息来计算出执行计划的代价,从而挑出最优的执行计划。
     
    当表没有做分析的时候,Oracle 会使用动态采样来收集统计信息,这个动作只有在SQL执行的第一次,即硬分析阶段使用,后续的软分析将不在使用动态采样,直接使用第一次SQL 硬分析时生成的执行计划。----------------ORACLE 的CBO 决定SQL的执行计划,可以理解为你例子中的是否走索引。 CBO 判断的依据就是表上的统计信息。 15楼的命令,就是收集了表上的统计信息。 统计信息越准确,执行计划就越准确。 
    在Oracle 10g中,有Job 每天晚上会自动的做统计信息的收集。 当然,如果在白天表上的data 变化很大,这时候的统计信息就可能不准确。 需要DBA 制定其他的统计信息收集job。Oracle Statistic 统计信息 小结
    http://blog.csdn.net/tianlesoftware/article/details/4668723
    推荐一本书:
    oracle 9i/10 编程艺术这本书就是针对开发人员的。 很不错。值得一看。