Сохраняет ли Postgres байтовые данные в шестнадцатеричном формате на сервере?

Чтобы работать со значениями bytea в PostgreSQL, я обычно сериализую в шестнадцатеричный формат и десериализую из него. Это кажется предпочтительным способом. Однако что на самом деле хранится на сервере PostgreSQL? Это шестнадцатеричный или нешестнадцатеричный двоичный файл? Причина, по которой меня это волнует, заключается в том, что hex, очевидно, будет занимать вдвое больше места, чем unhexed binary. Когда я говорю нешестнадцатеричный двоичный, я имею в виду, что шестнадцатеричная строка 00, состоящая из 2 байтов, представляет собой просто 0, то есть 1 байт, как нешестнадцатеричный двоичный код.

Контекст: у меня есть база данных Postgres и база данных Scylla, которые хранят одни и те же данные почти в одном и том же формате. Однако общее пространство, используемое Postgres, почти вдвое превышает пространство, используемое Scylla. Для Сциллы я не кодирую двоичный код как шестнадцатеричный. Я просто отправляю необработанный двоичный файл по сети. Я не ожидаю, что эти две базы данных будут использовать одинаковый объем пространства. Но для PostgreSQL использовать двойное пространство довольно много накладных расходов, и почти точное удвоение действительно заставляет меня подозревать, что данные хранятся на сервере в шестнадцатеричном, а не в двоичном формате (поскольку шестнадцатеричный использует ровно двойное пространство как фактический двоичный).


person CJ Cobb    schedule 24.03.2021    source источник


Ответы (1)


bytea хранится в двоичной форме, а не в шестнадцатеричном кодировании, что было бы чрезвычайно расточительно. Шестнадцатеричное представление — это просто текстовое представление по умолчанию, сгенерированное функцией вывода типа.

Я не знаю Scylla, поэтому не могу объяснить разницу, но у PostgreSQL есть значительные накладные расходы на строку (23 байта), а также есть некоторые накладные расходы на блок размером 8 КБ.

Вы говорите в своих комментариях, что измерили размер базы данных, которая включает в себя все метаданные и индексы. Я предлагаю вам использовать pg_table_size для измерения таблицы.

Обратите внимание, что PostgreSQL автоматически сжимает значения, если в противном случае строка таблицы превышала бы 2000 байт.

person Laurenz Albe    schedule 24.03.2021
comment
Я вычислил размер базы данных с помощью этой команды: SELECT pg_size_pretty( pg_database_size('dbname') ); - person CJ Cobb; 25.03.2021
comment
у вас есть источник, который говорит, что bytea хранится в двоичной форме, а не в шестнадцатеричном формате? - person CJ Cobb; 25.03.2021
comment
Я снова проверил размер базы данных сегодня (первоначально опубликованный вчера), и размер больше не ровно удваивается. 150 ГБ в Scylla — это около 275 ГБ в PostgreSQL. - person CJ Cobb; 26.03.2021
comment
Я добавил еще немного об измерении размера. Конечно, у меня есть источник информации о том, как хранится bytea: исходный код PostgreSQL, который открыт. Детали реализации не задокументированы. Но было бы безумием тратить место, сохраняя bytea другим способом. - person Laurenz Albe; 26.03.2021