Сколько места в байтах занимает для хранения ячейка с типом данных NUMBER(p)?

Не могу найти убедительного ответа на следующий вопрос.

Нужно узнать, как много места занимает для хранения значение типа данных NUMBER(p).

Например: NUMBER(1), NUMBER(3), NUMBER(8), NUMBER(10) и т.д..

create table t (x NUMBER(1), y NUMBER(10))
/
select COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE 
from user_tab_columns 
where table_name='T'; 

COLUMN_NAME  DATA_TYPE     DATA_LENGTH   DATA_PRECISION   DATA_SCALE
------------ ------------ ------------ ---------------- ------------
X            NUMBER                 22                1            0
Y            NUMBER                 22               10            0

Получается, независимо от точности, требуется 22 байта. Это действительно так?


Свободный перевод вопроса Oracle NUMBER(p) storage size? от участника @alex_pt


Ответы (1 шт):

Автор решения: 0xdb

Все чиселовые значения хранятся в виде поля переменной длины от 0 до 22 байт. Размер занимаемый для хранения зависит от фактического числового значения, а также от точности и количества знаков после запятой.

В документации Database Concepts / Numeric Data Types сказано:

Oracle Database stores numeric data in variable-length format. Each value is stored in scientific notation, with 1 byte used to store the exponent. The database uses up to 20 bytes to store the mantissa, which is the part of a floating-point number that contains its significant digits. Oracle Database does not store leading and trailing zeros.

Более интересно о хранении числовых значений повествуется в книге Expert Oracle Database Architecture (один из авторов: Томас Кайт). Цитирую (источник: блог Томаса Кайта):

It is interesting and useful to note that the NUMBER type is in fact a varying length data type on disk and will consume between 0 and 22 bytes of storage. Many times, programmers consider a numeric datatype to be a fixed length type and that is what they typically see when programming with 2 or 4 byte integers and 4 or 8 byte floats. The Oracle NUMBER type is similar to a varying length character string.

Можно посмотреть, что происходит с числами, содержащими разное количество значащих цифр. Создадим таблицу с двумя столбцами чисел и заполним первый столбец числами, содержащими 2, 4, 6, ..., 38 значащих цифр. Затем, просто добавим 1 к каждому из них:

create table t ( x number, y number )
/ 
insert into t (x, y)
    select x, x+1 from (
    select to_number (rpad ('9', rownum*2, '9')) x
    from dual connect by level<=19);

Стандартная функция VSIZE покажет, сколько места в байтах занимает значение в столбце:

                                       X                                        Y XS YS
---------------------------------------- ---------------------------------------- -- --
                                      99                                      100  2  2
                                    9999                                    10000  3  2
                                  999999                                  1000000  4  2
                                99999999                                100000000  5  2
                              9999999999                              10000000000  6  2
                            999999999999                            1000000000000  7  2
                          99999999999999                          100000000000000  8  2
                        9999999999999999                        10000000000000000  9  2
                      999999999999999999                      1000000000000000000 10  2
                    99999999999999999999                    100000000000000000000 11  2
                  9999999999999999999999                  10000000000000000000000 12  2
                999999999999999999999999                1000000000000000000000000 13  2
              99999999999999999999999999              100000000000000000000000000 14  2
            9999999999999999999999999999            10000000000000000000000000000 15  2
          999999999999999999999999999999          1000000000000000000000000000000 16  2
        99999999999999999999999999999999        100000000000000000000000000000000 17  2
      9999999999999999999999999999999999      10000000000000000000000000000000000 18  2
    999999999999999999999999999999999999    1000000000000000000000000000000000000 19  2
  99999999999999999999999999999999999999  100000000000000000000000000000000000000 20  2

При добавлении значащих цифр, требуемый объем памяти занимает все больше места. Каждые 2 цифры увеличивают объем памяти еще на один байт. Но если прибавить к этому значению единицу, что увеличит длину ещё на один знак, то занимаемое место постоянно 2 байта. БД пытается для сохранения числа выделить как можно меньше места. Для этого сохраняются значащие цифры, экспонента, используемая для десятичной точки, и знак числа (положительный или отрицательный).

Таким образом, чем больше значащих цифр содержит число, тем больше места для хранения оно требует.

Полезно знать, что числа хранятся в полях переменной длины. При попытке определить размер таблицы, например, чтобы оценить, какой объем памяти на диске потребуется для хранения 1.000.000 строк в таблице. Будут ли числа занимать 2 байта или 20 байт? Точно оценить размер таблицы без репрезентативных тестовых данных очень сложно.

→ Ссылка