版本: 11.2.0.2.0
我想验证我在手册中再次阅读的以下断言:
PLS_INTEGER数据类型具有这些 优于NUMBER数据类型的优势 和NUMBER个子类型:
PLS_INTEGER values require less storage.
我正在寻找有效使用的字节。
我知道Oracle内置数据类型和PL / SQL数据类型。 我再次阅读文档中的特定部分:
我查看了一些有用的功能:visze,dump(等等:长度,长度b)。 我在这里以及其他论坛/博客中搜索过,即使过去看起来很明显,我也有点陷入困境。
我的虚拟程序(visize函数不会显示pls_integer的任何有效值,因为Tony Andrews在下面的答案中说明原因(注释13/07/11)
create or replace procedure TestSize
(
testPlsInteger in pls_integer
,testNumber in number
) is
sizePlsInteger pls_integer;
sizeNumber pls_integer;
FORMAT_DIM constant pls_integer := 15;
begin
select vsize(testPlsInteger), vsize(testNumber)
into sizePlsInteger, sizeNumber
from dual;
dbms_output.put_line('number:' || rpad(testPlsInteger, FORMAT_DIM)
||' PLS_INTEGER SIZE:' || rpad(sizePlsInteger, FORMAT_DIM)
|| ' NUMBER SIZE:' || sizeNumber);
end;
测试
begin
TestSize(2147483647, 2147483647);
TestSize(1, 1);
TestSize(1000000, 1000000);
TestSize(12345678, 12345678);
end;
结果
number:2147483647 PLS_INTEGER SIZE:6 NUMBER SIZE:6
number:1 PLS_INTEGER SIZE:2 NUMBER SIZE:2
number:1000000 PLS_INTEGER SIZE:2 NUMBER SIZE:2
number:12345678 PLS_INTEGER SIZE:5 NUMBER SIZE:5
- >>>>>>>>>> NEW SECTION ADDED 13/07/2011
遵循文件:
The PLS_INTEGER data type has these advantages over the NUMBER data type and NUMBER subtypes: PLS_INTEGER values require less storage.
和
The PLS_INTEGER data type stores signed integers in the range -2,147,483,648 through 2,147,483,647, represented in 32 bits.
数字数据类型应该比pls_integer需要更多的空间。 使用pls_integer大小的常量重写前一过程(32位,如文档所述),我们可以在下面看到它不是真的。
我认为这是由于数据类型“数字”的内部表示所致
使用 Tony Andrews 提供的“精彩”建议,并加载两个不同大小的不同数组(pls_integer和数字),似乎:
PS 显然,这种方法并不完全准确(就像Tony在帖子中写的那样)并与我的虚拟程序“TestSize”的输出相冲突, 规定计算“TestSize”中数字大小的方法(vsize for number)是正确的!
最后,我很少在生产代码中使用超过 100/200元素的数组,只需以避免PGA过载。 对于这个维度,怀疑仍然存在!
我必须做的其他研究才能发现这个“神谕”,这是我所不知道的;但出于这个原因,我写了这个问题! : - )
程序使用新的“Testsize”程序。
文档断言“PLS_INTEGER值需要更少存储”并非总是如此。
create or replace procedure TestSize
(
testNumber in number
) is
sizeNumber pls_integer;
SIZE_PLS_INTEGER constant pls_integer:= 4; -- always 32 bits(4 bytes)
FORMAT_DIM constant pls_integer := 15;
FORMAT_MINOR constant varchar2(1) := '<';
FORMAT_EQUAL constant varchar2(1) := '=';
begin
select vsize(testNumber)
into sizeNumber
from dual;
dbms_output.put_line('number:' || rpad(testNumber, FORMAT_DIM)
||' PLS_INTEGER SIZE:'
|| case when (SIZE_PLS_INTEGER<sizeNumber) then
rpad(SIZE_PLS_INTEGER, FORMAT_DIM,FORMAT_MINOR)
when (SIZE_PLS_INTEGER=sizeNumber) then
rpad(SIZE_PLS_INTEGER, FORMAT_DIM,FORMAT_EQUAL)
else rpad(SIZE_PLS_INTEGER, FORMAT_DIM)
end
|| ' NUMBER SIZE:'
|| case when (sizeNumber<SIZE_PLS_INTEGER) then
rpad(sizeNumber,FORMAT_DIM,FORMAT_MINOR)
else rpad( sizeNumber,FORMAT_DIM)
end);
end TestSize;
测试
begin
TestSize(2147483647);
TestSize(1);
TestSize(10);
TestSize(100);
TestSize(1000);
TestSize(1000);
TestSize(100000);
TestSize(1000000);
TestSize(10000000);
TestSize(10000000);
TestSize(100000000);
TestSize(1000000000);
TestSize(1000000000);
TestSize(90000000);
TestSize(9923);
TestSize(99232);
TestSize(555555);
TestSize(12345);
TestSize(1234);
TestSize(1000001);
TestSize(20000000000);
TestSize(12345678);
TestSize(12345678);
end;
结果
number:2147483647 PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:6
number:1 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:10 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:100 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:1000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:1000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:100000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:1000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:10000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:10000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:100000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:1000000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:1000000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:90000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:9923 PLS_INTEGER SIZE:4 NUMBER SIZE:3<<<<<<<<<<<<<<
number:99232 PLS_INTEGER SIZE:4============== NUMBER SIZE:4
number:555555 PLS_INTEGER SIZE:4============== NUMBER SIZE:4
number:12345 PLS_INTEGER SIZE:4============== NUMBER SIZE:4
number:1234 PLS_INTEGER SIZE:4 NUMBER SIZE:3<<<<<<<<<<<<<<
number:1000001 PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:5
number:20000000000 PLS_INTEGER SIZE:4 NUMBER SIZE:2<<<<<<<<<<<<<<
number:12345678 PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:5
number:12345678 PLS_INTEGER SIZE:4<<<<<<<<<<<<<< NUMBER SIZE:5
使用** Tony Andrews提供的“精彩”建议
虚拟程序“TestSize2”
create or replace procedure testSize2
(
testNum in pls_integer
,maxDim in pls_integer
,secondsToWait in pls_integer
) is
type TPlsIntegers is varray(100000) of pls_integer;
type TNumbers is varray(100000) of number;
pls TPlsIntegers := TPlsIntegers();
numbers TNumbers := TNumbers();
MODULE constant varchar2(20) := 'TestSize2';
PLS_ACTION constant varchar2(20) := 'pls_integer';
NUMBER_ACTION constant varchar2(20) := 'number';
SEP constant varchar2(3) := ' - ';
begin
dbms_application_info.set_action(action_name => PLS_ACTION||SEP||testNum ||SEP||maxDim);
pls.extend(maxDim);
for cont in 1 .. maxDim
loop
pls(cont) := testNum;
end loop;
dbms_lock.sleep(seconds => secondsToWait);
-- check pga with query
dbms_application_info.set_action(action_name => NUMBER_ACTION||SEP||testNum ||SEP||maxDim);
numbers.extend(maxDim);
for cont in 1 .. maxDim
loop
numbers(cont) := testNum;
end loop;
-- check pga with query
DBMS_LOCK.sleep(secondsToWait);
end;
测试
declare
MAX_TO_WAIT constant pls_integer := 3;
MODULE constant varchar2(30) := 'testSize2';
begin
debug.disable;
dbms_application_info.set_module(MODULE, action_name => '');
testSize2(testNum => 90000000, secondsToWait => MAX_TO_WAIT, maxDim => 100);
testSize2(testNum => 90000000, secondsToWait => MAX_TO_WAIT, maxDim => 10000); --10 000
testSize2(testNum => 90000000, secondsToWait => MAX_TO_WAIT, maxDim => 100000); --100 000
testSize2(testNum => 12345, secondsToWait => MAX_TO_WAIT, maxDim => 10000); --10 000
testSize2(testNum => 12345, secondsToWait => MAX_TO_WAIT, maxDim => 100000); --100 000
testSize2(testNum => 2147483647, secondsToWait => MAX_TO_WAIT, maxDim => 100);
testSize2(testNum => 2147483647, secondsToWait => MAX_TO_WAIT, maxDim => 10000); --10 000
testSize2(testNum => 2147483647, secondsToWait => MAX_TO_WAIT, maxDim => 100000); --100 000*\*\*/
dbms_application_info.set_action(action_name => 'END');
end;
查询以监控PGA
select vsst.sid || ',' || vses.serial# username, vsst.value,vses.MODULE,vses.ACTION
from v$sesstat vsst, v$statname vstt, v$session vses
where vstt.statistic# = vsst.statistic#
and vsst.sid = vses.sid
and vstt.name = 'session pga memory'
and vses.username = 'HR'
and vses.MODULE = 'testSize2'
注释结果
pls_integer number dif
-- size size size
-- n=90000000 DIM aRRAY= 100 528612 594148< DIF= 65536
-- n=90000000 DIM aRRAY= 10000 725220 1118436< DIF= 393216
-- n=90000000 DIM aRRAY= 100000 2101476 5771492> DIF= 3670016
-- n=12345 DIM aRRAY= 10000 921828 1380580< DIF= 458752
-- n=12345 DIM aRRAY= 100000 2101476 5771492> DIF= 3670016
-- n=2147483647 DIM aRRAY= 100 790756 856292 < DIF= 65536
-- n=2147483647 DIM aRRAY= 10000 921828 1380580< DIF= 458752
-- n=2147483647 DIM aRRAY= 100000 2101476 5771492> DIF= 3670016
答案 0 :(得分:8)
VSIZE
函数不会显示任何差异,因为它是一个重载函数,只能获取NUMBER,DATE或VARCHAR2值(请参阅SYS.STANDARD
的规范)。因此,当您传递一个PLS_INTEGER值时,该值首先隐式转换为NUMBER。
PLS_INTEGER的definition说
PLS_INTEGER数据类型存储 该范围内的有符号整数 -2,147,483,648到2,147,483,647,以32位表示。
所以总是32位= 4个字节。然而,如您所示,NUMBER的VSIZE()可以超过4个字节:
SQL> select vsize(2147483647) v from dual;
v
-
6
您可能能够看到差异的一种方法是,如果您运行一些PL / SQL来填充内存中的大量NUMBERS,并在之后查看会话的PGA使用情况。然后重复PLS_INTEGER。您可以使用小值和大值等重复实验。 (警告:PGA是以一定大小的块分配的,所以这不会完全准确,但足够大的阵列可能会显示出任何显着差异。)
要监控PGA使用情况,请使用以下查询:
select vsst.sid||','||vses.serial# username,
vsst.value
from v$sesstat vsst, v$statname vstt, v$session vses
where vstt.statistic# = vsst.statistic#
and vsst.sid = vses.sid
and vstt.name = 'session pga memory'
and vses.username = 'MYUSER';