Учитывая, что размер является переменным, я пытаюсь вычислить среднюю стоимость атрибута numeric(p, s). В моем случае numeric(10, 2).
Насколько я понимаю из документации Postgres, это означает, что у меня всего 10 цифр, из которых 2 не включают десятичную часть, следовательно, максимальное значение, которое я могу сохранить, равно 99999999,99.
Чего я не понимаю, так это вот эту часть документации:
Фактические требования к объему памяти составляют два байта для каждой группы из четырех десятичных цифр плюс служебные данные от трех до восьми байтов.
Мои два вопроса:
Я выполнил запрос со средним значением pg_column_size, что дало мне в общей сложности 6.95 байт. Однако я хочу знать, можно ли каким-либо образом рассчитать приблизительное значение, прежде чем проверять фактическое. (То же самое и с другими типами переменных в Postgres)

Если у меня есть две десятичные цифры, это означает, что требуемый объем памяти для них составит один байт?
Нет, 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 приводит к распаковке сохраненного значения, поэтому мы получаем размер оперативной памяти. Связанный:
Также обратите внимание, что хранение нулевых значений отличается. Видеть: