oracle 什么时候PLS_INTEGER实际上对性能有益?

ykejflvf  于 2023-11-17  发布在  Oracle
关注(0)|答案(1)|浏览(171)

看一下网上的例子,似乎pls_integer只对其他pls_integer的算术有用。在其他数据类型的算术中,它比number更有效吗?
运行如下测试(Oracle 19.0.0):

declare
  i integer;
  v_date_r date;
  v_months /*pls_integer*/ number := 7;
  v_days /*pls_integer*/ number := 98;
begin
  for i in 1..10000000 loop
    v_date_r := add_months(trunc(localtimestamp),-v_months) + v_days;
  end loop;
end;

个字符
使用pls_integer的测试通常优于使用number的测试。
为什么?为什么?
pls_integer不是转换成数字来计算sysdate + v_days吗?我的理解是转换了,那么怎么才能更快呢?
由于add_months()接受整数,因此当传入pls_integer而不是number时,函数会更快,即使它随后也会将v_days添加到结果中。
Oracle文档对此并不十分清楚。

xoefb8l8

xoefb8l81#

sysdatelocaltimestampadd_months等函数调用操作系统获取时间或进行复杂的日期操作所需的时间比对数字进行简单的算术运算所需的时间要多得多,因此,除非您构建的测试消除了这些昂贵的操作,否则无法真正测试pls_integernumber的性能。参数列表期望number(除非它们有pls_integer的特定重载)不会有帮助,因为Oracle会立即隐式地将它们转换为预期的数据类型。
number是一种在比二进制整数更高的级别上构造的人工数据类型,因此数字上的算术比二进制整数上的按位操作需要更多的高级代码步骤。但是很少有一段PL/SQL代码缺少比这些更昂贵的其他操作,所以选择pls_integer而不是number很少会有明显的区别。你必须有一个循环次数非常多的东西,而且里面除了数学什么都不做,就像这样:

declare
  j number;
  v_months number := 7;
  v_days number := 98;
  st timestamp with time zone;
begin
  st := systimestamp;
  for i in 1..100000000 loop
    j := GREATEST(i,5+v_months+v_days);
  end loop;
  
  dbms_output.put_line(systimestamp - st);
end;

字符串
在我的系统上,结果是+000000000 00:00:04.931385000。比较pls_integer

declare
  j pls_integer;
  v_months pls_integer := 7;
  v_days pls_integer := 98;
  st timestamp with time zone;
begin
  st := systimestamp;
  for i in 1..100000000 loop
    j := GREATEST(i,5+v_months+v_days);
  end loop;
  
  dbms_output.put_line(systimestamp - st);
end;


结果:+000000000 00:00:01.794718000,快了3倍。通过简单地测试循环迭代器本身可以看到同样的结果。比较:

declare
  i number := 0;
  st timestamp with time zone;
begin
  st := systimestamp;
  while i < 100000000 loop
    i := i + 1;
  end loop;
  
  dbms_output.put_line(systimestamp - st);
end;       

--> +000000000 00:00:03.044420000

declare
  i pls_integer := 0;
  st timestamp with time zone;
begin
  st := systimestamp;
  while i < 100000000 loop
    i := i + 1;
  end loop;
  
  dbms_output.put_line(systimestamp - st);
end;     

--> +000000000 00:00:01.017006000


所以pls_integer对于算术运算来说肯定更快。但是有多少人会写PL/SQL,在循环中只做数学运算,有这么多次迭代?而在一亿次迭代中,我只节省了2秒。这将是一个非常罕见的情况,它实际上产生了足够的差异,值得在number上使用它。

相关问题