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

Oracle PL\SQL中数字数据类型的大小是多少,但不提供精度和规模?,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,我的新项目中的一个指导原则是在Oracle PL\SQL中指定精度和比例以及数字。开发人员手册说,如果未指定,则为每个变量分配22字节的默认大小 虽然我理解,在可能的情况下,指定精度和比例是很重要的。如果不提供精度,我似乎不同意分配22个字节 从Oracle文档中: “内部数字格式 Oracle数据库以可变长度格式存储数字数据。每个值以科学记数法存储,1字节用于存储指数,最多20字节用于存储尾数。结果值的精度限制为38位。Oracle数据库不存储前导零和尾随零。 例如,数字412以类似于4.1

我的新项目中的一个指导原则是在Oracle PL\SQL中指定精度和比例以及数字。开发人员手册说,如果未指定,则为每个变量分配22字节的默认大小

虽然我理解,在可能的情况下,指定精度和比例是很重要的。如果不提供精度,我似乎不同意分配22个字节

从Oracle文档中:

内部数字格式

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

我将上述文档发送给数据库架构师,但他似乎不同意我的观点


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

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>
您可以尝试使用数字约束,并看到它对内存分配没有影响内存是在实际设置任何值之前分配的,之后不会更改。在这个示例中,集合中的一个条目大约是48字节,但我预计集合条目本身会有一些显著的开销


关联数组和嵌套表分配相同的空间(因此我希望嵌套表在内部的实现方式与关联数组(即B-树)相同),VARRAY I达到410 MB,因此它的效率略高(也更快)。

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>
您可以尝试使用数字约束,并看到它对内存分配没有影响内存是在实际设置任何值之前分配的,之后不会更改。在这个示例中,集合中的一个条目大约是48字节,但我预计集合条目本身会有一些显著的开销

关联数组和嵌套表分配相同的空间(因此我希望嵌套表在内部的实现方式与关联数组(即B树)相同),VARRAY I达到410MB,因此它的效率略高(也更快)

但他似乎不同意我的意见

向他展示
vsize
功能的文档:

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

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

select vsize( 412), vsize( -412) from dual;
VSIZE(412)                             VSIZE(-412)
---------- ---------------------------------------
         3                                       4
另一项测试证明@Huskip的答案是正确的:

select vsize( 0.00000000000000000000000000000000000011 ), 
       vsize( 1.00000000000000000000000000000000000011)
from dual;
VSIZE(0.0000000000000000000000000000000 VSIZE(1.0000000000000000000000000000000
--------------------------------------- ---------------------------------------
                                      2                                      21
但他似乎不同意我的意见

向他展示
vsize
功能的文档:

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

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

select vsize( 412), vsize( -412) from dual;
VSIZE(412)                             VSIZE(-412)
---------- ---------------------------------------
         3                                       4
另一项测试证明@Huskip的答案是正确的:

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

我不明白。您是在询问PL/SQL程序中的数字,还是在Oracle(SQL)数据库的表中存储了什么?您多次提到PL/SQL,但都链接到Oracle数据库文档。到目前为止,您得到的两个答案是关于数据库中存储的内容。我不确定PL/SQL的内存分配,但我当然希望它在编译时进行分配(动态内存分配非常耗时)。如果是这样的话,那么它实际上是根据您的声明而不是实际使用的值来分配内存的。如果是这样,您的开发人员指南对于PL/SQL是正确的。@mathguy抱歉,我指的是PL\SQL。但是Husqvik在下面的答案中建议的vsize测试似乎仍然有效。实际上,否。@Husqvik的答案显示了数字的内部存储格式(数字如何存储在磁盘上,或者如果要保存它,它将如何存储)。PL/SQL对数字声明的作用是它分配内存(而不是磁盘存储)-完全不同的概念。我找不到PL/SQL内存分配机制的文档,但是在它使用动态内存分配的地方,即对于长varchar2变量,有很多关于它的讨论。几乎可以肯定的是,数字的内存是静态分配的。这意味着,如果不提供精度和规模,编译器必须假设“最坏情况”并分配最大值,即使您在程序中知道这是不需要的。因此,在编写PL/SQL程序时,您需要考虑精度和规模,即使在数据库中的大多数应用程序(SQL,用于存储)中,您也不需要考虑,因为存储与内存不同,是根据实际数值动态分配的。@mathguy,因为Oracle PL/SQL文档(我知道)没有提到关于
number
数据类型的内存管理动态,我只是假设程序员无法控制它。这也意味着,无论您是定义数字
number(1)
还是
number(38)
,内存足迹都是相同的。我的记忆测试似乎也验证了这一点(PGA变化总是相同的,并且与数字精度无关)。所有这些也意味着OP的开发者手册是不正确的。我不知道