在建立函数索引的时候,自定义的函数需要加Deterministic
确定性函数的性能好处是如果使用相同的输入调用函数两次,Oracle可以记住第一个调用的结果因此避免在第二次执行时再次调用。
但是该功能直到10g Release 2才被真正实施。
环境11g
测试1:
create or replace package deter_body is v_glo_count pls_integer:=0; end deter_body; --可以定义全局变量,这里先不用,还要归零操作,麻烦 create or replace function deter_fun(num pls_integer) return pls_integer as begin dbms_output.put_line('访问flag'); return num; end deter_fun;
--观察输出结果 --这种调用,每一行都会访问一次, 因为操作的是筛选后的行值 select deter_fun(5) from emp e where e.deptno=20; --发现deter_fun的调用次数为emp的记录数,可怕,相当于,先全表调一次函数,再使用条件 select * from emp e where e.deptno= deter_fun(20);
--加Deterministic create or replace function deter_fun(num pls_integer) return pls_integer Deterministic as begin dbms_output.put_line('访问flag'); return num; end deter_fun;
--可以看到 --访问一次 select deter_fun(5) from emp e where e.deptno=20; --访问一次 select * from emp e where e.deptno= deter_fun(20);
--4次 select deter_fun(level) from dual connect by rownum<5; |
例2:
create or replace function deter_fun2 return pls_integer as v_val number; begin v_val:=trunc(dbms_random.value(0,999)); dbms_output.put_line('访问flag'); return v_val;
end deter_fun2; --访问14次 select * from emp e where e.empno=deter_fun2();
--我们加上Deterministic看看 create or replace function deter_fun2 return pls_integer Deterministic as v_val number; begin v_val:=trunc(dbms_random.value(0,999)); dbms_output.put_line('访问flag'); return v_val;
end deter_fun2;
--只访问一次 select * from emp e where e.empno=deter_fun2(); 通过执行计划的递归调用次数也可以看出来,大家可以验证 |