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