sql语句如下:select /*+index(t,PK_aidszh_sgra_adult_info_his)*/
 f.id_record as id,
 f.zonecode as postcode,
 (select cnname
    from zonecode
   where zonecode = substr(f.zonecode, 1, 2) || '000000') as prov,
 (select cnname
    from zonecode
   where zonecode = substr(f.zonecode, 1, 4) || '0000') as city,
 (select cnname
    from zonecode
   where zonecode = substr(f.zonecode, 1, 6) || '00') as district,
 f.orgcode as site_code,
 (select orgname from aidszh_sgra_organise where orgcode = f.ORGCODE) as site_name,
 t.antin as card_code,
 t.pid as ptid,
 t.patient_name as name,
 t.id as ic,
 f.addrcode as addr_county,
 (select ZONENAME from zonecode where zonecode = f.addrcode) as addr_name,
 f.addr1 as addr_town,
 f.addr as addr_door,
 f.flwno as visit_n,
 (case
   when f.is_flw = 1 and f.clinic_treatment <> 3 then
    '1'
   when f.end_cause = 1 then
    '2'
   when f.end_cause = 2 then
    '3'
   when f.end_cause = 3 then
    '4 '
   when (f.clinic_treatment = 3 and f.is_flw = 1) then
    '5'
   else
    '1'
 end) as flw_status,
 f.CD4 as f5cd4,
 f.CD8 as f5cd8,
 to_char(f.DT_CD8BLOOD, 'yyyy-mm-dd') as f5cdt,
 f.VIRULN as f5vl, f.OTHER_CLINIC as fother
  from aidszh_sgra_adult_info_his    t,
       aidszh_sgra_adult_newstatus_h h,
       aidszh_sgra_adult_flw_his     f
 where t.card_id = f.card_id
   and t.FLAG = 2
   and t.card_id = h.card_id
   and f.ZONECODE like '210726%'
   and f.TM_CREATE < to_date('2010-06-01', 'yyyy-mm-dd')
其中,aidszh_sgra_adult_info_his 数据量8w,
aidszh_sgra_adult_newstatus_h 数据量8w,aidszh_sgra_adult_flw_his 数据量80w目前执行时间为3.5s,执行计划如下:我发现以上执行计划表AIDSZH_SGRA_ADULT_NEWSTATUS_H走全表扫描,于是建了一个索引,在看执行计划,的确走了索引,但效率并没有提高,还是3.5s。请sql高手帮忙优化一下,控制在2s以内!

解决方案 »

  1.   

    只是略看了下,按理说连接的几个表数据量非常小,PL/DEV运行出现数据不应该要这么长时间,按照以下方法排查下:
    1、select字句先不用特定数据,直接用*
    2、aidszh_sgra_adult_flw_his表的ZONECODE、TM_CREATE和FLAG等是否有索引
    3、aidszh_sgra_adult_info_his和aidszh_sgra_adult_newstatus_h 2个8W数据的表的card_id要有索引
    4、如果上面3个步骤之后不慢,那就是select中的子查询慢;
    5、如果还是慢,那就是aidszh_sgra_adult_flw_his建的索引,再从步骤一开始慢慢查看。
      

  2.   

    1、把select 中的列变成*效率提高了0.2秒,所以select中的列不应该是优化的对象。
    2、where语句出了flag没有索引,其他的都有索引。flag一共就两个值没有加索引的必要。
      

  3.   

    如果都建了索引的话,又试了ls的方法的话。可以试下把where 后面调整一下顺序:
    看是否能起到优化的作用
    调整后的顺序如下: where  t.FLAG = 2 
       and  t.card_id = h.card_id
       and  t.card_id = f.card_id
       and f.ZONECODE like '210726%'
       and f.TM_CREATE < to_date('2010-06-01', 'yyyy-mm-dd')
      

  4.   

    单独分析aidszh_sgra_adult_flw_his试试
    select * from aidszh_sgra_adult_flw_his 
    where f.ZONECODE like '210726%'
    and f.TM_CREATE < to_date('2010-06-01', 'yyyy-mm-dd');要是这都慢,就从这个表优化。
      

  5.   

    LZ先把你的优化器改成All Rows,别用Choose,另外,才这么点数据量就不要走索引了,另外Zonecode是个什么表, (select cnname
        from zonecode
       where zonecode = substr(f.zonecode, 1, 2) || '000000') as prov,
    这个看起来怎么这么别扭。
      

  6.   

    建议按照调整where 条件的顺序并给T.FLAG 添加位图索引oca_ocp_ocm 
      

  7.   

    你应该多贴一点,看一下CBO分析的cost及结果集大小。强制/*+index(t,PK_aidszh_sgra_adult_info_his)*/没有意义啊,根本没有用到这个索引的字段,你这么做就是先对索引全扫之后按照这个索引的结果集扫表,比全扫还消耗还高。f上索引对应的是哪个字段?区分度如何?