Oracle PL \ SQL中Number数据类型的大小是多少,不提供精度和规模?

时间:2016-12-19 18:26:41

标签: oracle plsql oracle11g

我的新项目的一个指导方针是指定精度&与Oracle PL \ SQL中的NUMBER一起扩展。开发人员手册说如果没有指定,则为每个变量分配22个字节的默认大小。

虽然我知道指定精度和重要性是很重要的。如果没有提供精度,我似乎并不同意分配22个字节。

http://docs.oracle.com/cd/B28359_01/server.111/b28318/datatype.htm#CNCPT1834

来自oracle docs:

" 内部数字格式

Oracle数据库以可变长度格式存储数字数据。每个值都以科学计数法存储,1个字节用于存储指数,最多20个字节用于存储尾数。结果值限制为38位精度。 Oracle数据库不存储前导零和尾随零。例如,数字412以类似于4.12×102的格式存储,其中1个字节用于存储指数(2),2个字节用于存储尾数(4,1,2)的三个有效数字。负数包括其长度的符号。"

我将上述文档发送给数据库架构师,但他似乎并不认同我。

如果我们不指定精度& oracle pl \ sql中NUMBER数据类型的比例是需要22个字节还是只有足够的字节来存储分配给它的值?

2 个答案:

答案 0 :(得分:1)

NUMBER相当于NUMBER(*)。精度和比例仅限于可接受的值,并且不会影响内存分配。

HUSQVIK@HQ_PDB_TCP> DECLARE
  2      item_count CONSTANT NUMBER := 10000000;
  3      TYPE t_collection IS TABLE OF NUMBER(38);
  4      data t_collection := t_collection();
  5
  6      PROCEDURE print_allocated_memory IS
  7          allocated_memory NUMBER;
  8      BEGIN
  9          SELECT
 10              value INTO allocated_memory
 11          FROM
 12              v$statname
 13              JOIN v$mystat ON v$statname.statistic# = v$mystat.statistic#
 14          WHERE
 15              name = 'session pga memory';
 16
 17          dbms_output.put_line('Allocated memory: ' || round(allocated_memory / 1048576, 1) || ' MB');
 18      END;
 19  BEGIN
 20      print_allocated_memory;
 21
 22      data.extend(item_count);
 23
 24      print_allocated_memory;
 25
 26      FOR i IN 1..item_count  LOOP
 27          data(i) := 1.00000000000000000000000000000000000011;
 28      END LOOP;
 29
 30      print_allocated_memory;
 31  END;
 32  /
Allocated memory: 3.5 MB
Allocated memory: 483.8 MB
Allocated memory: 483.8 MB

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.04
HUSQVIK@HQ_PDB_TCP>

您可以尝试NUMBER约束并查看它对内存分配没有影响在实际设置任何值之前分配内存,之后它不会更改。在示例中,集合中的一个条目大约是48个字节,但我预计集合条目本身会有一些显着的开销。

关联数组和嵌套表分配相同的空间(所以我希望嵌套表在内部实现与关联数组(B-tree)相同),VARRAY我得到410 MB所以它的效率稍高(也更快) )。

答案 1 :(得分:1)

  

但他似乎并不认同我。

向他展示vsize功能的文档:http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions213.htm#i80071

  

VSIZE 返回内部表示中的字节数   EXPR。如果expr为null,则此函数返回null。

简单地证明他412占用3个字节,而-412占用4个字节:

select vsize( 412), vsize( -412) from dual;
VSIZE(412)                             VSIZE(-412)
---------- ---------------------------------------
         3                                       4

另一项测试证明@Husquick的回答是正确的:

select vsize( 0.00000000000000000000000000000000000011 ), 
       vsize( 1.00000000000000000000000000000000000011)
from dual;
VSIZE(0.0000000000000000000000000000000 VSIZE(1.0000000000000000000000000000000
--------------------------------------- ---------------------------------------
                                      2                                      21