oracle数据库引擎转换

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值