Размер числового байта (точность, масштаб) в Postgres

Учитывая, что размер является переменным, я пытаюсь вычислить среднюю стоимость атрибута numeric(p, s). В моем случае numeric(10, 2). Насколько я понимаю из документации Postgres, это означает, что у меня всего 10 цифр, из которых 2 не включают десятичную часть, следовательно, максимальное значение, которое я могу сохранить, равно 99999999,99.

Чего я не понимаю, так это вот эту часть документации:

Фактические требования к объему памяти составляют два байта для каждой группы из четырех десятичных цифр плюс служебные данные от трех до восьми байтов.

Мои два вопроса:

  • Если у меня есть две десятичные цифры, это означает, что требуемый объем памяти для них составит один байт?
  • Если у меня есть от трех до восьми байтов служебных данных, как я могу узнать, какое значение соответствует моему случаю?

Я выполнил запрос со средним значением pg_column_size, что дало мне в общей сложности 6.95 байт. Однако я хочу знать, можно ли каким-либо образом рассчитать приблизительное значение, прежде чем проверять фактическое. (То же самое и с другими типами переменных в Postgres)

ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
1
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если у меня есть две десятичные цифры, это означает, что требуемый объем памяти для них составит один байт?

Нет, numeric с двумя цифрами занимает 5 байт на диске и 8 байт в оперативной памяти.

Если у меня есть от трех до восьми байтов служебных данных, как я могу узнать, какое значение соответствует моему случаю?

Как в инструкции написано:

два байта для каждой группы из четырех десятичных цифр

Для каждой стартовой группы из четырех десятичных цифр, если быть точным. Итак, мы можем вычислить:

ceil(digits / 4.0) * 2

плюс от трех до восьми байтов служебных данных.

Минимальные издержки в 3 байта применяются только к «0» в «упакованном» формате на диске. Еще:

  • 2 байта накладных расходов для любых цифр (кроме особого случая 0)
    Или + 4 байта служебных данных для более чем 256 цифр.

  • 3 байта служебных данных в «упакованном» формате, который используется для хранения на диске
    Или + 6 байт накладных расходов, если объем памяти превышает 128 байт или для хранения в оперативной памяти.

Знак, десятичная точка и пробелы в числе не влияют на размер хранилища.
Модификаторы типа (точность и масштаб) типа numeric также несущественны.

Вот демо с формулами для полного расчета:

SELECT id, digits
     , pg_column_size(n) AS disk_size
     , CASE
          WHEN n = 0         THEN 3                           -- efficient storage of 0
          WHEN digits <= 248 THEN 3 + ceil(digits / 4.0) * 2  -- "packed" format for size <= 128 bytes 
          WHEN digits <= 256 THEN 6 + ceil(digits / 4.0) * 2  -- effecitve size > 128 bytes
          ELSE                    8 + ceil(digits / 4.0) * 2  -- more than 256 digits
       END AS expected_disk_size
     , pg_column_size(n + 0) AS ram_size
        , CASE
          WHEN n = 0         THEN 6                           -- efficient storage of 0
          WHEN digits <= 256 THEN 6 + ceil(digits / 4.0) * 2  -- effecitve size > 128 bytes
          ELSE                    8 + ceil(digits / 4.0) * 2  -- more than 256 digits
       END AS expected_ram_size
FROM   tbl
     , length(translate(n::text, '-. ', '')) AS digits;       -- only digits matter

рабочий пример

Обратите внимание, что отсутствие операции n + 0 приводит к распаковке сохраненного значения, поэтому мы получаем размер оперативной памяти. Связанный:

Также обратите внимание, что хранение нулевых значений отличается. Видеть:

Другие вопросы по теме

Похожие вопросы

Как получить значение только из таблицы?
Пользовательская сортировка фрейма данных на основе нескольких столбцов
Соберите данные OPC-UA с помощью Telegraf в QuestDB в плотном формате
Как лучше всего создать таблицу событий, в которой каждый раз при обновлении события предоставляются разные элементы событий?
Восстановление базы данных neo4j в контейнере Docker из файла .backup
Ошибка Подключение к локальному хосту: 5432 отклонено. Убедитесь, что имя хоста и порт верны и что почтмейстер принимает соединения TCP/IP
PrismaClient не может работать в этой среде браузера или был включен в состав браузера (работает в «неизвестном») при обновлении
Как сделать левое соединение, чтобы ключи могли иметь множественную степень детализации с помощью Spark?
Обновить данные с помощью laravel
Сортировка MySQL с использованием MAX() для GROUP BY возвращает неверные данные