oracle数据库引擎转换

来源:互联网 发布:战地1玩家数据 编辑:程序博客网 时间:2024/06/05 08:12

oracle数据库可以运行众多不同的引擎,如sql,plsql,java,c等,不同引擎之间的转换会消耗大量的CPU资源。

java与c的引擎我们使用较少,主要是使用sql与plsql引擎,其中sql引擎是标准sql处理引擎,而plsql引擎主要是用于处理序列、函数、过程、包等,如果一个SQL语句同时嵌套了函数,则会在执行的过程中涉及到sql与lsql的引擎转换。

举一个简单的例子,在过程中,我们把函数结果赋值给一个变量有两种方式:
1、直接赋值:
变量名:=函数名(参数);

2、通过伪表dual查询赋值:
select 函数名(参数) into 变量名 from dual;

第一种方式只使用了plsql引擎,而第二种方式同时使用了sql与plsql引擎,在赋值时,需要进行引擎转换。

这个引擎转换的开销究竟有多大,我们还是通过一个实例进行比较:
无引擎转换代码如下:

DECLARE  V_BEGIN        NUMBER(10);  V_END          NUMBER(10);  V_I            NUMBER(10);  V_CURRTIME     NUMBER(12,2);  V_USETIME      NUMBER(12,2);  V_DATE         DATE;BEGIN  SELECT VALUE INTO V_BEGIN FROM V$SESS_TIME_MODEL WHERE SID=SYS_CONTEXT('USERENV','SID') AND STAT_NAME='DB CPU';  V_CURRTIME:=DBMS_UTILITY.GET_TIME;  FOR V_I IN 1..100000    LOOP      V_DATE:=SYSDATE;--      SELECT SYSDATE INTO V_DATE FROM DUAL;    END LOOP;  V_USETIME:=(DBMS_UTILITY.GET_TIME-V_CURRTIME)/100;  DBMS_LOCK.SLEEP(15);  SELECT VALUE INTO V_END FROM V$SESS_TIME_MODEL WHERE SID=SYS_CONTEXT('USERENV','SID') AND STAT_NAME='DB CPU';  DBMS_OUTPUT.PUT_LINE('无引擎转换耗时:'||TO_CHAR(V_USETIME,'990.00')||'秒,CPU消耗次数:'||TO_CHAR(V_END-V_BEGIN));END;有引擎转换代码如下:DECLARE  V_BEGIN        NUMBER(10);  V_END          NUMBER(10);  V_I            NUMBER(10);  V_CURRTIME     NUMBER(12,2);  V_USETIME      NUMBER(12,2);  V_DATE         DATE;BEGIN  SELECT VALUE INTO V_BEGIN FROM V$SESS_TIME_MODEL WHERE SID=SYS_CONTEXT('USERENV','SID') AND STAT_NAME='DB CPU';  V_CURRTIME:=DBMS_UTILITY.GET_TIME;  FOR V_I IN 1..100000    LOOP--      V_DATE:=SYSDATE;      SELECT SYSDATE INTO V_DATE FROM DUAL;    END LOOP;  V_USETIME:=(DBMS_UTILITY.GET_TIME-V_CURRTIME)/100;  DBMS_LOCK.SLEEP(15);  SELECT VALUE INTO V_END FROM V$SESS_TIME_MODEL WHERE SID=SYS_CONTEXT('USERENV','SID') AND STAT_NAME='DB CPU';  DBMS_OUTPUT.PUT_LINE('有引擎转换耗时:'||TO_CHAR(V_USETIME,'990.00')||'秒,CPU消耗次数:'||TO_CHAR(V_END-V_BEGIN));END;

运行结果分别如下:
无引擎转换耗时: 0.07秒,CPU消耗次数:78125
有引擎转换耗时: 1.94秒,CPU消耗次数:1953125

分析:
不管是运行时间及CPU消耗,如果产生了引擎转换,消耗的代价都在20倍以上,而这类无意中转换引擎的语句大量出现在我们的代码中,仅通过伪表dual赋值的代码就有近2600处,另如:
insert into 表 (时间列..) values (sysdate…);
insert into 表 (ID列..) values (序列值…);
update 表 set 列=函数值 where 条件
等语句都是大量存在。

而这些语句只要换种写法,效率就可以大幅提高:
1、任何时候都要避免使用伪表给变量赋值。而应该直接对变量赋值,除非是只能用于SQL语句的函数,如decode。
2、如果SQL语句中的需要用到函数,请先用变量将函数暂存,在语句中直接绑定变量;

我们在书写任何SQL语句的时候,一定要考虑以下问题:
1、这个语句会使用哪种数据库引擎,是否会使用到两种或两种以上的引擎?
2、如果用到了两种或两种以上的引擎,能否通过拆解决变成多条语句,每条语句都只使用一个引擎?如果能,那就拆解。

当然,如果是将一张表的数据处理后写入另一张表之类的批量处理,且insert语句中存在类似序列、函数类处理的时候,如果要拆解,就必须使用游标逐行处理,使用游标显然比批量处理要消耗更多的资源,因此,这类引擎转换是可以接受的。

2 0
原创粉丝点击