免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1016 | 回复: 0
打印 上一主题 下一主题

[RAID与磁盘阵列] Oracle11新特性——PLSQL新特性(四) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-07-16 10:19 |只看该作者 |倒序浏览
Oracle在调用函数的时候可以将调用过程直接替换为子查询的代码,这样可以避免在运行过程中调用开销,Oracle提供了一个新的PRAGMA INLINE来指示函数是否进行INLINE优化:
SQL> CREATE OR REPLACE FUNCTION F_TEST (P_IN IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 IF P_IN > 1 THEN
4 RETURN P_IN + F_TEST(P_IN - 1);
5 ELSE
6 RETURN 1;
7 END IF;
8 END;
9 /
函数已创建。
SQL> CREATE OR REPLACE FUNCTION F_TEST_INLINE (P_IN IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 IF P_IN > 1 THEN
4 PRAGMA INLINE (F_TEST_INLINE, 'YES');
5 RETURN P_IN + F_TEST_INLINE(P_IN - 1);
6 ELSE
7 RETURN 1;
8 END IF;
9 END;
10 /
函数已创建。
分别建立两个递归调用的函数,一个使用了11g提供的PRAGMA INLINE,强制Oracle对函数F_TEST_INLINE进行INLINE优化,看看调用两个函数所需的时间:
SQL> SET TIMING ON
SQL> SELECT F_TEST_INLINE(1000000) FROM DUAL;
F_TEST_INLINE(1000000)
----------------------
5.0000E+11
已用时间: 00: 00: 01.32
SQL> SELECT F_TEST(1000000) FROM DUAL;
F_TEST(1000000)
---------------
5.0000E+11
已用时间: 00: 00: 18.68
SQL> SELECT F_TEST_INLINE(1000000) FROM DUAL;
F_TEST_INLINE(1000000)
----------------------
5.0000E+11
已用时间: 00: 00: 00.42
SQL> SELECT F_TEST(1000000) FROM DUAL;
F_TEST(1000000)
---------------
5.0000E+11
已用时间: 00: 00: 00.57
无论是第一次调用,还是第二次调用,使用了INLINE的方法都比普通调用有一个明显的性能提升。
除了强制使用PRAGMA INLINE方法外,Oracle还提供了自动INLINE的方式,只需要将初始化参数PLSQL_OPTIMIZE_LEVLE设置为3,Oracle会自动选择合适的过程进行INLINE优化:
SQL> SHOW PARAMETER PLSQL_OPTIMIZE_LEVEL
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
plsql_optimize_level integer 2
SQL> ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL = 3;
会话已更改。
SQL> CREATE OR REPLACE FUNCTION F_TEST (P_IN IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 IF P_IN > 1 THEN
4 RETURN P_IN + F_TEST(P_IN - 1);
5 ELSE
6 RETURN 1;
7 END IF;
8 END;
9 /
函数已创建。
SQL> SELECT F_TEST(1000000) FROM DUAL;
F_TEST(1000000)
---------------
5.0000E+11
已用时间: 00: 00: 00.40
SQL> SELECT F_TEST(1000000) FROM DUAL;
F_TEST(1000000)
---------------
5.0000E+11
已用时间: 00: 00: 00.46
可以看到设置了自动优化功能,F_TEST函数的调用也达到了PRAGMA INLINE函数的相同效果。需要说明的是,INLINE优化在大部分情况下会带来性能的提升,但是这个性能的提升是以占用更多的内存为代价的。下面看看两种方式的统计差别:
SQL> ALTER SESSION SET PLSQL_OPTIMIZE_LEVEL = 2;
会话已更改。
SQL> CREATE OR REPLACE FUNCTION F_TEST (P_IN IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 IF P_IN > 1 THEN
4 RETURN P_IN + F_TEST(P_IN - 1);
5 ELSE
6 RETURN 1;
7 END IF;
8 END;
9 /
函数已创建。
SQL> CREATE OR REPLACE FUNCTION F_TEST_INLINE (P_IN IN NUMBER) RETURN NUMBER AS
2 BEGIN
3 IF P_IN > 1 THEN
4 PRAGMA INLINE (F_TEST_INLINE, 'YES');
5 RETURN P_IN + F_TEST_INLINE(P_IN - 1);
6 ELSE
7 RETURN 1;
8 END IF;
9 END;
10 /
函数已创建。
SQL> SET SERVEROUT ON
SQL> DECLARE
2 V_NUMBER1 NUMBER;
3 V_NUMBER2 NUMBER;
4 V_RES NUMBER;
5 BEGIN
6
7 INSERT INTO T_SESSION_STAT SELECT 1, 'STAT:' || NAME, VALUE
8 FROM V$SESSTAT A, V$STATNAME B
9 WHERE A.STATISTIC# = B.STATISTIC#
10 AND A.SID = (SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1)
11 UNION ALL
12 SELECT 1, 'LATCH:' || NAME, GETS VALUE FROM V$LATCH;
13
14 V_NUMBER1 := DBMS_UTILITY.GET_TIME;
15 V_RES := F_TEST_INLINE(1000000);
16 V_NUMBER1 := DBMS_UTILITY.GET_TIME - V_NUMBER1;
17
18 INSERT INTO T_SESSION_STAT SELECT 2, 'STAT:' || NAME, VALUE
19 FROM V$SESSTAT A, V$STATNAME B
20 WHERE A.STATISTIC# = B.STATISTIC#
21 AND A.SID = (SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1)
22 UNION ALL
23 SELECT 2, 'LATCH:' || NAME, GETS VALUE FROM V$LATCH;
24
25 V_NUMBER2 := DBMS_UTILITY.GET_TIME;
26 V_RES := F_TEST(1000000);
27 V_NUMBER2 := DBMS_UTILITY.GET_TIME - V_NUMBER2;
28
29 INSERT INTO T_SESSION_STAT SELECT 3, 'STAT:' || NAME, VALUE
30 FROM V$SESSTAT A, V$STATNAME B
31 WHERE A.STATISTIC# = B.STATISTIC#
32 AND A.SID = (SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1)
33 UNION ALL
34 SELECT 3, 'LATCH:' || NAME, GETS VALUE FROM V$LATCH;
35
36 DBMS_OUTPUT.PUT_LINE(&#39

1 EXECUTE ' || V_NUMBER1/100 || ' SECONDS');
37 DBMS_OUTPUT.PUT_LINE(&#39

2 EXECUTE ' || V_NUMBER2/100 || ' SECONDS');
38
39 FOR C IN
40 (
41 SELECT *
42 FROM
43 (
44 SELECT A.NAME, C.VALUE + A.VALUE - 2 * B.VALUE VALUE
45 FROM
46 T_SESSION_STAT A,
47 T_SESSION_STAT B,
48 T_SESSION_STAT C
49 WHERE A.NAME = B.NAME
50 AND A.NAME = C.NAME
51 AND A.ID = 1
52 AND B.ID = 2
53 AND C.ID = 3
54 )
55 WHERE ABS(VALUE) > 100
56 ) LOOP
57 DBMS_OUTPUT.PUT_LINE(RPAD(C.NAME, 50, ' ') || C.VALUE);
58 END LOOP;
59
60 END;
61 /
P1 EXECUTE 1.4 SECONDS
P2 EXECUTE 2.26 SECONDS
STAT:session pga memory 89194496
PL/SQL 过程已成功完成。
Oracle的inline操作将调用操作直接替换为程序的代码,避免了调用的开销,获得了明显的性能提升,但是这种方法消耗更多的PGA内容也是显而易见的。
对于特别复杂的调用情况,或者递归、循环调用次数过多,可能会造成INLINE调用方式的内存占用过大,从而导致性能下降甚至出现内存耗尽的情况。INLINE带来的并非总是性能的提升,使用不当也可能造成严重的性能问题。
Oracle提供的PRAGMA INLINE同样可以强制禁止过程INLINE优化的发生。

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/66684/showart_1083155.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP