同事写的程序中,有这样一个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;
数据库的开发,需要的是执行速度最快的程序,而不是代码量最少的程序。所以要尽可能地提高自己代码的执行速度。