日期:2014-05-17  浏览次数:20789 次

如何避免这个SQL语句的全表扫描
Select   1     from   fexpense               e,

              fconsign               c,

              csubchargeitem   s,

              ccustsuppview     csv,

              cuser                     cu1,

              cuser                     cu2

  where   (e.fexp_creator   =   ?   or   exists   (select   f.FCSG_CONSIGN_ID   from   FCONSIGN   f   where   f.fcsg_consign_id=e.fexp_consign_id   and   f.fcsg_creator   =   : "SYS_B_04 "))
      and   e.fexp_consign_id   =   c.fcsg_consign_id(+)

      and   e.fexp_charge_id   =   s.csci_ci_id(+)

      and   e.fexp_settlerment_object   =   csv.accountNumber(+)

      and   c.fcsg_creator   =   cu1.cusr_user_id(+)

      and   c.fcsg_canvasser   =   cu2.cusr_user_id(+)

      and   (e.fexp_forward_flag   >   ?   or   e.fexp_forward_flag   <   ?)

      and   (e.fexp_cancel_flag   >   ?or   e.fexp_cancel_flag   <   ?)

      and   (e.fexp_lump_flag   >   ?or   e.fexp_lump_flag   <   ?)

      and   e.fexp_org_id   =   ?

  order   by   e.fexp_settlerment_object   ASC,   e.fexp_currency_code   ASC

看了执行计划,提示fexpense表做了全表扫描,我对该表的WHERE条件中的字段做了个联合索引,还是提示全表,有什么解决办法

------解决方案--------------------
exist结果就全是真的,估计你想要的是
(e.fexp_creator = ? or e.fexp_creator in (select f.FCSG_CONSIGN_ID from FCONSIGN f where f.fcsg_creator = : "SYS_B_04 "))
这样,就会用fexpense的fexp_creator索引了

------解决方案--------------------
Analyze Table fexpense compute Statistics; ---更新数据统计

alter index index_name rebuild; -----如果索引没有生效则重编译

因为oracle的优化器默认是按照choose 的,而不是基于规则的。