与Number相比,Pls_integer值需要“更少”的存储空间。如何验证?

时间:2011-07-08 09:40:40

标签: oracle plsql

版本: 11.2.0.2.0

我想验证我在手册中再次阅读的以下断言:

  

PLS_INTEGER数据类型具有这些   优于NUMBER数据类型的优势   和NUMBER个子类型:

PLS_INTEGER values require less storage.

我正在寻找有效使用的字节。

我知道Oracle内置数据类型和PL / SQL数据类型。 我再次阅读文档中的特定部分:

Oracle data types

PL/SQL data types

我查看了一些有用的功能:viszedump(等等:长度,长度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需要更多的空间。 使用pls_integer大小的常量重写前一过程(32位,如文档所述),我们可以在下面看到它不是真的

我认为这是由于数据类型“数字”的内部表示所致

  • 但OP是“如何验证

使用 Tony Andrews 提供的“精彩”建议,并加载两个不同大小的不同数组(pls_integer和数字),似乎:

  1. 使用需要不同/相等存储的不同数字(前面提到的程序“TestSize”的输出)
  2. 使用varray在pl / sql中实现数组
  3. 测试这些阵列的不同尺寸10 000,100 000
  4. 包含10万个数字的大型数组需要比pls_integer更多的空间
  5. 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              
    

    • OP是“如何验证

    使用** 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
    

1 个答案:

答案 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';