Google

SQL优化的一个小例子

2007-12-03 20:59 来源: yuechaotian.cublog.cn 作者:yuechaotian 网友评论 0 条 浏览次数 106
 
同事写的程序中,有这样一个SQL:
    Select Max(aae002) 
      From AC21
   Where aac001 = '1304018693634'      --个人编号
       AND  aab001 = '13040191848'        --单位编号
       AND  aae002 <= '200703';              --月份
大意是根据指定单位编号、人员编号和月份,从AC21表中查询该人员不大于指定月份的最大月份。
 
由于数据量稍微大点,该SQL执行速度很慢。清空缓冲区后第一次执行大概需要11M。而一个单位中的所有人员记录都要执行一次这个SQL。使得业务变得非常慢。(以前我们还跟客户说,这是由于数据量很大,或者说是网络不速度不行,让他们“稍微”等会儿。哈哈。)
 
晚上第一次运行邯郸的系统测试时,发现有个模块很慢,就通过包:dbms_system.set_sql_trace_in_session 监测了一下该模块中的SQL,找到了执行最慢的SQL(上面那个)。
 
该SQL已经使用上了索引,想换一种SQL语句,效果也不好。于是将它改成了PL/SQL实现。速度变得相当快,提高了20-30倍左右。说白了很简单,就是根据指定的最大月份依次往下循环,找到后就跳出,找不到就赋值为'000000'。因为大部分数据在第一条就可以找到,所以执行很快(跟业务相关)。
 
function f_test ( prm_aab001 VARCHAR2,
                  prm_aac001 VARCHAR2,
                  prm_aae002 VARCHAR2) return VARCHAR2
IS
  v_aae002 VARCHAR2(6);
  v_aae002_return VARCHAR2(6);
BEGIN
  v_aae002 := prm_aae002;
  FOR i IN 1..120 LOOP
    v_aae002 := to_char(add_months(to_date(Prm_AAE002, 'yyyymm'), 1-i), 'yyyymm');
    BEGIN
      SELECT aae002
        INTO v_aae002_return
        FROM ac21
       WHERE AAC001 = prm_aac001
         AND AAB001 = prm_aab001
         AND aae002 = v_aae002;
    EXCEPTION 
      WHEN no_data_found THEN
        NULL;
    END;
    IF SQL%FOUND THEN RETURN v_aae002; END IF;
  END LOOP;
  RETURN '000000';
END;
 
数据库的开发,需要的是执行速度最快的程序,而不是代码量最少的程序。所以要尽可能地提高自己代码的执行速度。
上一篇: 下一篇:

相关主题:sql优化

网友评论