Значение Pls_integer требует «меньше» памяти по сравнению с Number. Как проверить? - PullRequest
5 голосов
/ 08 июля 2011

Версия: 11.2.0.2.0

Я хотел бы проверить следующее утверждение, которое я читаю в руководстве:

Тип данных PLS_INTEGER имеет эти преимущества по сравнению с типом данных NUMBER и NUMBER подтипы:

PLS_INTEGER values require less storage.

Я ищу эффективно используемые байты.

Я знаю встроенные типы данных Oracle и типы данных PL / SQL. Я снова прочитал конкретные разделы в документации:

Типы данных Oracle

Типы данных PL / SQL

Я рассмотрел некоторые полезные функции: visze , dump (и так далее: length, lengthb). Я искал здесь и в других форумах / блогах, и даже если это кажется очевидным, чему я научился в прошлом, я немного застрял.


Моя фиктивная процедура (функция visize не будет показывать никаких допустимых значений для pls_integer, потому что причина , показанная Тони Эндрюсом в его ответе ниже (примечание 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;

Test

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

- >>>>>>>>> ДОБАВЛЕН НОВЫЙ РАЗДЕЛ 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 бита, как говорит документ), мы можем видеть ниже, что это не так .

Полагаю, это связано с внутренним представлением типа данных "число"

  • Но ОП был " как проверить "

Используя предложение " great ", данное Tony Andrews , и загружая два разных массива разных размеров (pls_integer и number), кажется, что:

  1. Использование разных чисел, которые требуют разного / одинакового хранения (вывод ранее упомянутой процедуры "TestSize")
  2. Использование varray для реализации массива в pl / sql
  3. Тестирование различных размеров для этих массивов 10 000, 100 000
  4. Большие массивы из 100 000 чисел требуют больше места , чем у pls_integer.

PS Очевидно, этот метод не совсем точен (как писал Тони в своем посте) и сталкивается с выводом моей фиктивной процедуры "TestSize", при условии, что метод для вычисления размера чисел в "TestSize" (vsize для числа) является правильным!

Наконец, я редко использую массив из более чем 100/200 элементов в своем производственном коде, просто , чтобы избежать перегрузки PGA. И для этого измерения остается сомнение!

Другие исследования, которые я должен сделать, чтобы обнаружить этого «оракула», который находится за пределами моих знаний; но по этой причине я написал этот вопрос! : -)


Процедура с использованием новой процедуры "Размер теста".

Утверждение документации "Для значений 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;

Test

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              

  • ОП был " как проверить "

Используя предложение " great ", данное ** Тони Эндрюсом

Пустая процедура "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;

Test

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 Ответ

8 голосов
/ 08 июля 2011

Функция VSIZE не будет показывать никакой разницы, потому что это перегруженная функция, которая может принимать только значения NUMBER, DATE или VARCHAR2 (см. Спецификацию SYS.STANDARD). Поэтому, когда вы передаете ему значение PLS_INTEGER, это значение сначала неявно преобразуется в NUMBER.

определение PLS_INTEGER говорит

Типы данных PLS_INTEGER целые числа со знаком в диапазоне От 2 147 483 648 до 2 147 483 647, представленные в 32 битах.

Так что это всегда 32 бита = 4 байта. В то время как, как вы показали, VSIZE () NUMBER может быть больше 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';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...