2011-07-08 1117 views
5

Versión: 11.2.0.2.0El valor de Pls_integer requiere "menos" almacenamiento que el Número. Cómo verificar?

me gustaría para verificar la afirmación de seguimiento estoy leyendo de nuevo en el manual:

El PLS_INTEGER tipo de datos tiene estas ventajas sobre el NÚMERO datos de tipo y NUMBER subtipos:

PLS_INTEGER values require less storage. 

Estoy buscando bytes efectivamente utilizados.

Conozco los tipos de datos incorporados de Oracle y los tipos de datos PL/SQL. leí de nuevo las secciones específicas en la documentación:

Oracle data types

PL/SQL data types

He revisado algunas funciones útiles: visze, dump (y así sucesivamente: longitud, lengthb). He buscado aquí y en otros foros/blogs, e incluso si parece algo obvio aprendido en el pasado, estoy un poco atrapado.


Mi ficticia procedimiento (función visize no mostrará los valores válidos para PLS_INTEGER porque la razón ilustrada por Tony Andrews, en su respuesta a continuación (nótese 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; 

prueba

begin 
    TestSize(2147483647, 2147483647); 
    TestSize(1, 1); 
    TestSize(1000000, 1000000); 
    TestSize(12345678, 12345678); 
end; 

012 Resultados

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 

- >>>>>>>>> NUEVA SECCIÓN AÑADIDO 13/07/2011

Después de la documentación:

The PLS_INTEGER data type has these advantages over the NUMBER data type and NUMBER subtypes: 
PLS_INTEGER values require less storage. 

y

The PLS_INTEGER data type stores signed integers in the range -2,147,483,648 through 2,147,483,647, represented in 32 bits. 
  • afirmación de documentación "valores PLS_INTEGER requieren menos almacenamiento " no siempre es cierto.

Debe ser cierto que el tipo de datos de número debe requerir más espacio que pls_integer. Reescribiendo el procedimiento anterior utilizando una constante para tamaño pls_integer (32 bits como dice el documento), podemos ver a continuación no es verdadero.

supongo que es debido a la representación interna del "número" tipo de datos

  • Pero el PO era "cómo verificar"

Usando el "gran "sugerencia dada por Tony Andrews, y cargando dos diferentes matrices de diferentes tamaños (pls_integer y número), parece que:

  1. El uso de diferentes números que requieren igual almacenamiento/diferente (salida del procedimiento anteriormente mencionado "TestSize")
  2. Usando VARRAY para implementar matriz en PL/SQL
  3. Testing dimensión diferente para estos array 10 000, 100 000
  4. Las grandes matrices de 100 000 números requieren más espacio que las pls_integer.

PS Obviamente, este método no es totalmente exacta (como Tony escribió en su post) y chocan con la salida de mi procedimiento de prueba "TestSize", siempre que el método para calcular los números el tamaño en "TestSize" (vsize para el número) es correcto!

FINALMENTE, raramente utilizo una matriz de más de 100/200 elementos en mi código de producción, solo para evitar sobrecargar PGA. ¡Y para estas dimensiones la duda permanece!

Otros estudios que tengo que hacer para descubrir este "oráculo", eso está más allá de mi conocimiento; ¡pero por esta razón escribí esta pregunta! :-)


Procedimiento utilizando el nuevo procedimiento de "Testsize".

Aserción de documentación "Los valores de PLS_INTEGER requieren menos almacenamiento " no siempre es cierto.

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; 

prueba

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; 

Resultados

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    

  • El PO fue "cómo verificar "

Usando el" "sugerencia dada por **, Tony Andrews

procedimiento simulado "gran 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; 

prueba

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; 

de consultas para supervisar 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' 

anotada Resultados

          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

Nueva sección añadida 13/07/2011 – zep

Respuesta

8

La función VSIZE no mostrará ninguna diferencia porque es una función sobrecargada que puede tomar un número, la fecha o el valor VARCHAR2 solamente (vea la especificación de SYS.STANDARD). Entonces, cuando le pasa un valor PLS_INTEGER, ese valor se convierte implícitamente a NUMBER primero.

El definition de PLS_INTEGER dice

El tipo de almacenes de datos PLS_INTEGER enteros con signo en el rango -2147483648 través 2147483647, representados en 32 bits.

Por lo tanto, siempre es 32 bits = 4 bytes. Considerando que, como se mostró, el VSIZE() de un número puede ser más de 4 bytes:

SQL> select vsize(2147483647) v from dual; 

v 
- 
6 

Una forma que puede ser capaz de ver la diferencia es si ejecuta algunos PL/SQL que rellena una gran variedad de NÚMEROS en la memoria, y mira el uso de PGA para tu sesión antes de un después. Luego repite para PLS_INTEGER. Podría repetir el experimento con valores pequeños y grandes, y así sucesivamente. (Advertencia: PGA se asigna en trozos de un cierto tamaño, por lo que este no será totalmente exacta, pero una gran variedad suficiente puede mostrar cualquier diferencia significativa.)

para supervisar el uso PGA utilizar una consulta como:

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'; 
+0

+1 Gracias. ¿Hay alguna manera de verificar el tamaño de un pls_integer o tengo que aceptar los 32 bits sin para verlo? – zep

+0

Gracias.Ok, he visto la actualización, esto significa que en algún momento PLS_INTEGER requiere más bytes que un NUMBER, como para el número 1? – zep

+1

Sí, creo que sí, consulte la última actualización anterior para conocer la diferencia. –

Cuestiones relacionadas