INSERT INTO B21_01
  (APB001, --APB001 NUMBER(4)    Y                年              
   APB002, --APB002 NUMBER(2)    Y                月              
   AAB301, --AAB301 VARCHAR2(6)                   地域            
   AAE043, --AAE043 VARCHAR2(6)                   数据期别        
   AAC003, --AAC003 VARCHAR2(30) Y                姓名            
   AAC002, --AAC002 VARCHAR2(18)                  身份证          
   AAC001, --AAC001 VARCHAR2(14)                  个人编号        
   AAC006, --AAC006 VARCHAR2(8)  Y                生日            
   AAC004, --AAC004 VARCHAR2(3)  Y                性别            
   AAC005, --AAC005 VARCHAR2(3)  Y                民族            
   AAC009, --AAC009 VARCHAR2(3)  Y                户口性质        
   AAC011, --AAC011 VARCHAR2(3)  Y                文化程度        
   AJC093, --AJC093 VARCHAR2(3)  Y                失业原因        
   AJC094, --AJC094 VARCHAR2(8)  Y                本次失业登记日期 
   AAB019, --AAB019 VARCHAR2(3)  Y                失业前所在单位类型 
   AAB020, --AAB020 VARCHAR2(3)  Y                失业前所在单位经济类型 
   AAB022, --AAB022 VARCHAR2(6)  Y                失业前所在单位行业类型 
   AAE170, --AAE170 VARCHAR2(3)  Y                享受失业保险状态 
   ACA111, --ACA111 VARCHAR2(7)  Y                原从事职业工种  
   AAC014, --AAC014 VARCHAR2(3)  Y                专业技术职务    
   AAC015, --AAC015 VARCHAR2(3)  Y                职业资格等级    
   AJC00B, --AJC00B NUMBER(3)    Y                失业登记前连续就业月数 
   AAC013, --AAC013 VARCHAR2(3)  Y                原用工形式      
   AJC00C, --AJC00C NUMBER(3)    Y                接受培训次数    
   AAC215, --AAC215 NUMBER(3)    Y                接受推荐次数    
   AJC00D, --AJC00D NUMBER(3)    Y                接受指导次数    
   AJC00M, --AJC00M VARCHAR2(3)  Y                灵活就业标志    
   ACE119, --ACE119 VARCHAR2(8)  Y                注销失业登记时间 
   AJC00A, --AJC00A VARCHAR2(3)  Y                注销失业登记原因 
   AJC00G, --AJC00G VARCHAR2(3)  Y                再就业单位类型  
   AJC00H, --AJC00H VARCHAR2(3)  Y                再就业单位经济类型 
   AJC00I, --AJC00I VARCHAR2(6)  Y                再就业单位行业类型 
   AJC00J, --AJC00J VARCHAR2(7)  Y                再就业职业(工种) 
   AJC00L, --AJC00L VARCHAR2(3)  Y                安置公益性岗位标志 
   AJC00N, --AJC00N VARCHAR2(3)  Y                自谋职业标志    
   APC004, --APC004 NUMBER(1)    Y                是否新增人员,后更新,默认为0 
   APC011, --APC011 VARCHAR2(3)  Y                年龄段,后更新   
   APC006, --APC006 NUMBER(4)    Y                年龄,直接根据生日计算出来年龄 
   APC012, --APC012 VARCHAR2(3)  Y                接受培训情况    
   APC013, --APC013 VARCHAR2(3)  Y                接受推荐情况    
   APC014) --APC014 VARCHAR2(3)  Y                接受指导情况    
  SELECT V_YEAR,
         V_MON,
         T.AAB301,
         T.AAE043,
         TRIM(T.AAC003),
         T.AAC002,
         T.AAC001,
         T.AAC006,
         DECODE(TRIM(T.AAC004), '1', '1', '2', '2', NULL, '000', '999'), --性别
         COMMON_FUN_UTIL.GET_ZB180('AAC005', TRIM(T.AAC005)),
         DECODE(TRIM(T.AAC009), '1', '10', '2', '20', NULL, '000', '999'), --户口性质
         COMMON_FUN_UTIL.GET_ZB180('AAC011', TRIM(T.AAC011)),
         COMMON_FUN_UTIL.GET_ZB180('AJC093', TRIM(T.AJC093)),
         T.AJC094,
         DECODE(TRIM(T.AAB019),
                '10',
                '10',
                '20',
                '50',
                '30',
                '30',
                '40',
                '70',
                NULL,
                '000',
                '999'), --失业前所在单位类型
         COMMON_FUN_UTIL.GET_ZB180('AAB020', TRIM(T.AAB020)),
         COMMON_FUN_UTIL.GET_ZB180('AAB022', TO_NUMBER(TRIM(T.AAB022))),
         COMMON_FUN_UTIL.GET_ZB180('AAE170', TRIM(T.AAE170)),
         COMMON_FUN_UTIL.GET_ZB180('ACA111', TRIM(T.ACA111)),
         DECODE(TRIM(T.AAC014),
                '1',
                '1',
                '2',
                '2',
                '3',
                '3',
                '4',
                '4',
                NULL,
                '000',
                '999'), --专业技术职务
         DECODE(TRIM(T.AAC015),
                '1',
                '1',
                '2',
                '2',
                '3',
                '3',
                '4',
                '4',
                '5',
                '5',
                '0',
                '0',
                NULL,
                '000',
                '999'), --职业资格等级
         T.AJC00B,
         DECODE(TRIM(T.AAC013),
                '1',
                '1',
                '2',
                '2',
                '3',
                '3',
                '4',
                '4',
                '9',
                '9',
                NULL,
                '000',
                '999'), --原用工形式
           T.AJC00C,
         T.AAC215,
         T.AJC00D,
         DECODE(TRIM(T.AJC00M), '1', '1', '0', '0', NULL, '000', '999'), --灵活就业标志
         T.ACE119,
         DECODE(TRIM(T.AJC00A),
                '10',
                '10',
                '20',
                '20',
                '30',
                '30',
                '40',
                '40',
                '50',
                '50',
                '60',
                '60',
                '70',
                '70',
                '90',
                '90',
                NULL,
                '000',
                '999'), --注销失业登记原因
         DECODE(TRIM(T.AJC00G),
                '10',
                '10',
                '20',
                '50',
                '30',
                '30',
                '40',
                '70',
                NULL,
                '000',
                '999'), --再就业单位类型
         COMMON_FUN_UTIL.GET_ZB180('AAB020', TRIM(T.AJC00H)),
         COMMON_FUN_UTIL.GET_ZB180('AAB022', TRIM(T.AJC00I)),
         COMMON_FUN_UTIL.GET_ZB180('ACA111', TRIM(T.AJC00J)), --再就业职业工种
         DECODE(TRIM(T.AJC00L), '1', '1', '0', '0', NULL, '000', '999'), --安置公益性岗位标志
         DECODE(TRIM(T.AJC00N), '1', '1', '0', '0', NULL, '000', '999'), --自谋职业标志
         0, --APC004 NUMBER(1)    Y                是否新增人员,后更新,默认为0 
         COMMON_FUN_UTIL.GET_NLD(V_YEAR, T.AAC006), --APC011 VARCHAR2(3)  Y                年龄段,后更新   
         COMMON_FUN_UTIL.GET_NL(V_YEAR, T.AAC006), --APC006 NUMBER(4)    Y                年龄,直接根据生日计算出来年龄 
         COMMON_FUN_UTIL.GET_PXQK(NVL(T.AJC00C, -1)), --APC012 VARCHAR2(3)  Y                接受培训情况   
         COMMON_FUN_UTIL.GET_TJQK(NVL(T.AAC215, -1)), --APC013 VARCHAR2(3)  Y                接受推荐情况   
         COMMON_FUN_UTIL.GET_ZDQK(NVL(T.AJC00D, -1)) --APC014 VARCHAR2(3)  Y                接受指导情况    
    FROM JHK_JF11 T
   WHERE T.AAB301 LIKE V_V_AAB301
     AND T.AAE043 = V_AAE043;
   其中COMMON_FUN_UTIL.GET_ZB180这个函数的内容如下:  
  ------------------------------
  -- 转换80项指标代码到180项指标
  ------------------------------
  FUNCTION GET_ZB180(V_BBB100 IN VARCHAR2, V_BBB080 IN VARCHAR2)
  --V_BBB100 代码名称
    --V_BBB080 80项代码
   RETURN VARCHAR2 IS
    RESULT VARCHAR2(6);
    V_R    VARCHAR2(6);
  BEGIN
    IF V_BBB080 IS NULL OR TRIM(V_BBB080) IS NULL THEN
      RESULT := '000';
    ELSE
      BEGIN
        SELECT BBB180
          INTO V_R
          FROM BB10 T
         WHERE T.BBB100 = V_BBB100
           AND T.BBB080 = V_BBB080
           AND ROWNUM < 2;
      EXCEPTION
        WHEN NO_DATA_FOUND THEN
          RESULT := '999';
      END;
      IF V_R IS NULL OR TRIM(V_R) IS NULL THEN
        RESULT := '999';
      ELSE
        RESULT := V_R;
      END IF;
    END IF;
    RETURN(RESULT);
  END;
而GET_NLD()与GET_NL及GET_PXQK(),GET_TJQK(),GET_ZDQK()函数中不用查询其它表,基本就是case when.......我就不例出来,
上面的insert语句,我加工一个市一个月的数据用了1573秒多(这个月数据有53372条),而JHK_JF11总的记录数才589121。好慢。我知道慢的原因是因为多次调用GET_ZB180()这个函数,而没办法,我必须做新老代码转换。将jf11的代码值对应为现在的新代码值。另外jf11表有(aab301,aae043)的复合索引。
请高手帮我优化下这个代码。是不是一个一个字段去更新会快点???

解决方案 »

  1.   


    description                   对象所有者  对象名称  耗费  基数    字节      cpu耗费  IO耗费
    insert statement,goaL=choose                      3    464    152192             3
    table access by index rowid    tzjhk    jf11      3    464    152192             3
      index range scan             tzjhk    pk_jf11   2    8358                      2
      

  2.   


    --改了一下,及时地return RESULT,不用进行后面的判断:FUNCTION GET_ZB180(V_BBB100 IN VARCHAR2, V_BBB080 IN VARCHAR2)
      RETURN VARCHAR2 IS
      RESULT VARCHAR2(6);
      V_R    VARCHAR2(6);
    BEGIN
      IF nvl(V_BBB080, 0) = 0 THEN
        return RESULT := '000';
      ELSE
        BEGIN
          SELECT BBB180
            INTO V_R
            FROM BB10 T
           WHERE T.BBB100 = V_BBB100
             AND T.BBB080 = V_BBB080
             AND ROWNUM < 2;
        EXCEPTION
          WHEN NO_DATA_FOUND THEN
            return RESULT := '999';
        END;
        IF nvl(V_R, 0) = 0 THEN
          return RESULT := '999';
        ELSE
          RESULT := V_R;
        END IF;
      END IF;
      RETURN(RESULT);
    END;
      

  3.   

    函数重新编译一下:create or replace FUNCTION...
      

  4.   

    to:BlueskyWide谢谢你的提意.应该可以快很多.我去试下.省了好多操作.呵~~
      

  5.   

    有什么方法可以直接快速的释放回滚段啊???在insert的时候还没commit我就直接在emc中将会话给killed了。只有等到没有回滚段了才能继续之前的操作。
      

  6.   

    T.BBB100 和 T.BBB080 上没建索引?
      

  7.   

    有索引INX_BB10 on BB10 (BBB100, BBB080, BBB180)
      

  8.   

    我现在没办法试BlueskyWide说的方法,因为我的那个过程没锁了,到现在还没释放掉.另外BlueskyWide中的return RESULT := '000';
    有语法错误,应该直接改为return ('000');
      

  9.   

    这个查询语句能优化的地方好像没什么了。现在如果不执行insert,只执行insert下面的select语句速度怎么样?
    如果很快,那就要在insert上改动了。
      

  10.   

    -- 用这个函数会更省:
    FUNCTION GET_ZB180(V_BBB100 IN VARCHAR2, V_BBB080 IN VARCHAR2)
       RETURN VARCHAR2 IS
        RESULT VARCHAR2(6) := '000';
      BEGIN
          BEGIN
            SELECT NVL(TRIM(BBB180),'999')
              INTO RESULT
              FROM BB10 T
             WHERE T.BBB100 = V_BBB100
               AND T.BBB080 = V_BBB080
               AND ROWNUM < 2;
          EXCEPTION
            WHEN NO_DATA_FOUND THEN
              RESULT := '999';
          END;
        RETURN(RESULT);
      END;
      

  11.   

    我直接select出来确实很快,27000条数据需时150秒。我觉的很快了。这样的话,怎么去改insert啊??只不是查出来的记录太多,insert时没有急时去commit啊?所以比较慢??怎么改??
      

  12.   

    这样就是需要改动insert,查询SQL已经可以了。1.首先表上是否有insert触发器?如果有,可在像这样'批量'insert时禁用,insert完成后执行一个过程来实现触发器功能。2.考虑对insert的表,在insert前:
    alter table xxx nologging;
    insert /*+ append*/ into xxx(...
      

  13.   

    commit的问题,针对‘提高速度’来说,是越少越好。
    只要回滚段足够大,和不怕锁表影响业务。
      

  14.   


    1) 你把GET_ZB180()这个函数的调用都注释点,多少秒
    2) 你把GET_ZB180()这个函数改成:
    create or replace function get_zb180(..)
    ..
    is
    begin
      return '1';
    end;然后测试,多少秒?
      

  15.   

    我晕死了,刚刚把那个insert语句,直接从存储过程中copy出来,放到sql窗体直接执行时,非常快。才十几秒。但我执行过程,跟踪时,一到这个insert的地方就非常慢,已经过去很久了还没执行完这步操作,到底是怎么回事啊?还请高手多多指教啊!
      

  16.   

    绑定变量的问题,你在sql中执行,看看执行计划,如果用上了索引,就在存储过程中加上强制索引改一个这些参数,看看有没有作用:
    sql>alter session set sqlOPTIMIZER_INDEX_COST_ADJ = 40;
      

  17.   

    哈哈,我刚试了下,好象快了不少了,在select后面加了个/*+ rule*/。居然在过程中不加这个规则,我的select用不上索引,哎……折腾我好久,才知道我昨天就加/*+ rule*/试下咯,狂晕
      

  18.   

    sql>alter session set OPTIMIZER_INDEX_COST_ADJ = 40; 
      

  19.   

    问题真的很多,也很怪哦!我最开始一直都是在test窗口,测试我的过程,要等好久才能执行完,所以我就一步一步跟进去,发现insert的地方执行要很久。就一直想优化这个insert sql语句。但刚,我直接在command窗体执行过程,也就是用exec run_task_xz21('321200','200803','200803');这样执行只花了16秒。为什么在test过程时,我输入过程需要的参数值('321200','200803','200803')后直接点执行时,会那么慢啊??真是奇了怪了。
      

  20.   

    test window擅长单步调试,而command window擅长解释执行,分配的空间可能有很大的不同。 
    你的程序在test window中执行的时候可能有多次回滚和页面的频繁调进调出。系统产生了抖动可能你还没有查觉呢?!
      

  21.   

    呵,现在在command窗体测试这个过程,加工一个市的数据,时间为200801-200808,数据量为214291只用了230秒。已经很快了。都怪我自己。要谢谢楼上各位了。一位就结贴。以表谢意!!