Chinaunix首页 | 论坛 | 博客
  • 博客访问: 11590631
  • 博文数量: 8065
  • 博客积分: 10002
  • 博客等级: 中将
  • 技术积分: 96708
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-16 17:06
文章分类

全部博文(8065)

文章存档

2008年(8065)

分类: 服务器与存储

2008-07-16 10:21:43

以前取SEQUENCE的NEXTVAL和CURRVAL只能通过SQL语句,现在可以在PL/SQL中通过赋值语句获取:

SQL> CREATE SEQUENCE S_ID;

序列已创建。

SQL> SET SERVEROUT ON
SQL> DECLARE
2 V_ID NUMBER;
3 BEGIN
4 V_ID := S_ID.NEXTVAL;
5 DBMS_OUTPUT.PUT_LINE(V_ID);
6 END;
7 /
1

PL/SQL 过程已成功完成。

这种方法比使用SELECT INTO要方便,更重要的是,由于不执行SQL语句,这种方式的效率更高。

SQL> CREATE SEQUENCE S_1;

序列已创建。

SQL> CREATE SEQUENCE S_2;

序列已创建。

SQL> CREATE OR REPLACE PROCEDURE P1 AS
2 V_SEQ NUMBER;
3 BEGIN
4 FOR I IN 1..100000 LOOP
5 SELECT S_1.NEXTVAL INTO V_SEQ FROM DUAL;
6 END LOOP;
7 END;
8 /

过程已创建。

SQL> CREATE OR REPLACE PROCEDURE P2 AS
2 V_SEQ NUMBER;
3 BEGIN
4 FOR I IN 1..100000 LOOP
5 V_SEQ := S_2.NEXTVAL;
6 END LOOP;
7 END;
8 /

过程已创建。

SQL> SET TIMING ON
SQL> EXEC P1

PL/SQL 过程已成功完成。

已用时间: 00: 00: 06.81
SQL> EXEC P2

PL/SQL 过程已成功完成。

已用时间: 00: 00: 06.35
SQL> EXEC P1

PL/SQL 过程已成功完成。

从SQL的运行时间上看,二者的差别不大,使用赋值的方法似乎略快一些。不过采用赋值的方法最大的好处是可以减少LATCH,在多用户并发访问的情况下效率更高。

下面通过查询V$SESSTAT视图和V$LATCH视图,分布记录两个存储过程的执行统计信息,并将二者的差异显示出来。

在执行之前,需要先建立一张临时表:

SQL> SET TIMING OFF
SQL> CREATE GLOBAL TEMPORARY TABLE T_SESSION_STAT
2 (ID NUMBER, NAME VARCHAR2(100), VALUE NUMBER);

表已创建。

SQL> SET SERVEROUT ON
SQL> DECLARE
2 V_NUMBER1 NUMBER;
3 V_NUMBER2 NUMBER;
4 BEGIN
5
6 INSERT INTO T_SESSION_STAT SELECT 1, 'STAT:' || NAME, VALUE
7 FROM V$SESSTAT A, V$STATNAME B
8 WHERE A.STATISTIC# = B.STATISTIC#
9 AND A.SID = (SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1)
10 UNION ALL
11 SELECT 1, 'LATCH:' || NAME, GETS VALUE FROM V$LATCH;
12
13 V_NUMBER1 := DBMS_UTILITY.GET_TIME;
14 P1;
15 V_NUMBER1 := DBMS_UTILITY.GET_TIME - V_NUMBER1;
16
17 INSERT INTO T_SESSION_STAT SELECT 2, 'STAT:' || NAME, VALUE
18 FROM V$SESSTAT A, V$STATNAME B
19 WHERE A.STATISTIC# = B.STATISTIC#
20 AND A.SID = (SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1)
21 UNION ALL
22 SELECT 2, 'LATCH:' || NAME, GETS VALUE FROM V$LATCH;
23
24 V_NUMBER2 := DBMS_UTILITY.GET_TIME;
25 P2;
26 V_NUMBER2 := DBMS_UTILITY.GET_TIME - V_NUMBER2;
27
28 INSERT INTO T_SESSION_STAT SELECT 3, 'STAT:' || NAME, VALUE
29 FROM V$SESSTAT A, V$STATNAME B
30 WHERE A.STATISTIC# = B.STATISTIC#
31 AND A.SID = (SELECT SID FROM V$MYSTAT WHERE ROWNUM = 1)
32 UNION ALL
33 SELECT 3, 'LATCH:' || NAME, GETS VALUE FROM V$LATCH;
34
35 DBMS_OUTPUT.PUT_LINE('1 EXECUTE ' || V_NUMBER1/100 || ' SECONDS');
36 DBMS_OUTPUT.PUT_LINE('2 EXECUTE ' || V_NUMBER2/100 || ' SECONDS');
37
38 FOR C IN
39 (
40 SELECT *
41 FROM
42 (
43 SELECT A.NAME, C.VALUE + A.VALUE - 2 * B.VALUE VALUE
44 FROM
45 T_SESSION_STAT A,
46 T_SESSION_STAT B,
47 T_SESSION_STAT C
48 WHERE A.NAME = B.NAME
49 AND A.NAME = C.NAME
50 AND A.ID = 1
51 AND B.ID = 2
52 AND C.ID = 3
53 )
54 WHERE ABS(VALUE) > 100
55 ) LOOP
56 DBMS_OUTPUT.PUT_LINE(RPAD(C.NAME, 50, ' ') || C.VALUE);
57 END LOOP;
58
59 END;
60 /
P1 EXECUTE 6.29 SECONDS
P2 EXECUTE 6.34 SECONDS
STAT:session pga memory 131072
STAT:redo size -308
STAT:undo change vector size 292
LATCH:cache buffers chains -171
LATCH:redo allocation -103
LATCH:shared pool simulator -99993

PL/SQL 过程已成功完成。

二者的执行时间仍然相差不多,上面的差异中redo和undo都不是关注的内容,采用SELECT INTO的方式会导致共享池的争用,而采用赋值的方式会占用更多的PGA内存。

LATCH是串行操作,一遍情况下内存不是问题,因此应该尽量选择来提高并发性能。不过根据测试也可以看到,二者的性能差异很小,选择哪种方法都不会带来明显的性能变化。
阅读(307) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~