您在这里:首页 > 学员专区 > 技术文章
Oracle视频
Oracle
CUUG课程

利用DETERMINISTIC声明提高性能(二)

 


虽然Oracle提供的DETERMINISTIC声明,本意是确保函数的确定性,但是如何合理利用,是可以用来提高性能的。

这一篇描述参数顺序对性能的影响。

 

 

上一篇文章提到了,如果希望通过DETERMINISTIC来获取性能收益,那么采用批量方式是必须的,而且数组的值相对而言越大对于性能的帮助会越大。

但是这里存在一个问题,如果需要处理的数据量本身很大,虽然重复的输入参数不少,但是总的参数不同的值更多,那么即使将ARRAY的值设置到1000,能带来的性能收益也很有限,因为即使1000次调用,也不能保证参数完全一样出现多次,而如果无限制的增大ARRAY,虽然从DETERMINISTIC函数的角度讲可以提高性能,但是对于内存的占用等其他方面,会带来性能的下降,显然一味的扩大批量并不是问题的解决之道。

其实解决这个问题很简单,就是在调用DETERMINISTIC函数之前,对函数的参数进行排序,确保相同的参数顺序调用,这样DETERMINISTIC函数执行的次数最少。

继续使用上一篇文章的例子,看看排序后DETERMINISTIC函数的调用次数:

SQL> UPDATE T_DETER SET C = 1;

已更新15行。

已用时间: 00: 00: 00.17

SQL> SELECT ID, F_DETER(C), F_SYSDATE FROM T_DETER;

       ID F_DETER(C) F_SYSDATE

---------- ---------- -------------------

        1         1 2011-05-26 14:26:12

        2         1 2011-05-26 14:26:13

        3         1 2011-05-26 14:26:13

        4         1 2011-05-26 14:26:13

        5         1 2011-05-26 14:26:13

        6         1 2011-05-26 14:26:13

        7         1 2011-05-26 14:26:13

        8         1 2011-05-26 14:26:13

        9         1 2011-05-26 14:26:13

       10         1 2011-05-26 14:26:13

       11         1 2011-05-26 14:26:13

       12         1 2011-05-26 14:26:13

       13         1 2011-05-26 14:26:13

       14         1 2011-05-26 14:26:13

       15         1 2011-05-26 14:26:13

已选择15行。

1

1

已用时间: 00: 00: 02.29

SQL> SELECT ID, F_DETER(C), F_SYSDATE FROM (SELECT * FROM T_DETER ORDER BY C);

       ID F_DETER(C) F_SYSDATE

---------- ---------- -------------------

        1         1 2011-05-26 14:26:35

       15         1 2011-05-26 14:26:35

        3         1 2011-05-26 14:26:35

        4         1 2011-05-26 14:26:35

        5         1 2011-05-26 14:26:35

        6         1 2011-05-26 14:26:35

        7         1 2011-05-26 14:26:35

        8         1 2011-05-26 14:26:35

        9         1 2011-05-26 14:26:35

       10         1 2011-05-26 14:26:35

       11         1 2011-05-26 14:26:35

       12         1 2011-05-26 14:26:35

       13         1 2011-05-26 14:26:35

       14         1 2011-05-26 14:26:35

        2         1 2011-05-26 14:26:35

已选择15行。

1

已用时间: 00: 00: 01.10

可以看到,由于执行了排序,DETERMINISTIC函数不用再次检查输入参数是否相等,因此在SQL运行期间只调用了一次:

SQL> SHOW ARRAY

arraysize 15

SQL> SET ARRAY 1

SQL> SELECT ID, F_DETER(C), F_SYSDATE FROM (SELECT * FROM T_DETER ORDER BY C);

       ID F_DETER(C) F_SYSDATE

---------- ---------- -------------------

        1         1 2011-05-26 14:28:31

       15         1 2011-05-26 14:28:31

        3         1 2011-05-26 14:28:31

        4         1 2011-05-26 14:28:31

        5         1 2011-05-26 14:28:31

        6         1 2011-05-26 14:28:31

        7         1 2011-05-26 14:28:31

        8         1 2011-05-26 14:28:31

        9         1 2011-05-26 14:28:31

       10         1 2011-05-26 14:28:31

       11         1 2011-05-26 14:28:31

       12         1 2011-05-26 14:28:31

       13         1 2011-05-26 14:28:31

       14         1 2011-05-26 14:28:31

        2         1 2011-05-26 14:28:31

已选择15行。

1

已用时间: 00: 00: 01.17

即使将ARRAY设置为1,也对DETERMINISTIC的调用次数没有影响了。

下面看看多个参数值的情况:

SQL> UPDATE T_DETER SET C = MOD(ROWNUM, 2);

已更新15行。

已用时间: 00: 00: 00.03

SQL> SELECT ID, F_DETER(C), F_SYSDATE FROM (SELECT * FROM T_DETER ORDER BY C);

       ID F_DETER(C) F_SYSDATE

---------- ---------- -------------------

        2         0 2011-05-26 14:29:59

       14         0 2011-05-26 14:29:59

       12         0 2011-05-26 14:29:59

       10         0 2011-05-26 14:29:59

        8         0 2011-05-26 14:29:59

        6         0 2011-05-26 14:29:59

        4         0 2011-05-26 14:29:59

       11         1 2011-05-26 14:29:59

        7         1 2011-05-26 14:29:59

       13         1 2011-05-26 14:29:59

        5         1 2011-05-26 14:29:59

        9         1 2011-05-26 14:29:59

        3         1 2011-05-26 14:29:59

       15         1 2011-05-26 14:29:59

        1         1 2011-05-26 14:29:58

已选择15行。

1

0

已用时间: 00: 00: 02.08

即使ARRAY仍然为1,对于DETERMINISTIC函数也没有影响了,排序后DETERMINISTIC函数对于不同的参数值仅调用一次。

同时,这里也有一个有趣的现象,就是Oracle先执行的C=1的函数调用,然后才是C=0的调用。从SELECT查询返回的时间还有SERVEROUT的输出都证实了这一点,但是这与我们的理解不符,因为查询要求SQL先排序,然后运行函数,Oracle在这里并没有完全按照SQL的语法来运行,而是先调用了DETERMINISTIC函数,输出的时候再对结果排序。但由于指定了排序,事实上即使DETERMINISTIC函数即使在排序前调用,仍然使用了排序的特性,因此只运行了一次。

如果要使用DETERMINISTIC来提高函数的性能,最关键的一点是确保调用函数时,输入参数是排序的。

 


(以上内容摘于网络,如有侵权,请告之,将第一时间删除)

相关文章 [上一篇] 利用DETERMINISTIC声明提高性能(一)
010-88589926(88587026)
CUUG热门培训课程
Oracle DBA就业培训
CUUG名师
网络课程
技术沙龙
最新动态

总机:(010)-88589926,88589826,88587026 QQ讨论群:243729577 182441349 邮箱:cuug_bj@cuug.com
通信地址:北京市海淀区紫竹院路98号北京化工大学科技园609室(CUUG)邮政编码:100089 
中国UNIX用户协会 Copyright 2010  ALL Rights Reserved 北京神脑资讯技术有限公司
京ICP备11008061号  京公网安备110108006275号