Подтвердить что ты не робот

Нулевые столбцы занимают дополнительное пространство в PostgreSQL?

У меня есть таблица с 7 столбцами и 5 из них будут пустыми. Я буду иметь нулевые столбцы в типах int, text, date, boolean и money. Эта таблица будет содержать миллионы строк с множеством нулей. Я боюсь, что нулевые значения будут занимать пространство.

Кроме того, знаете ли вы, что Postgres индексирует нулевые значения? Я хотел бы предотвратить его индексирование нулей.

4b9b3361

Ответ 1

В принципе, значения NULL занимают 1 бит в растровом файле NULL. Но это не так просто.

нулевой битмап (для каждой строки) существует только там, если хотя бы один столбец в этой строке содержит значение NULL. Это может привести к эффекту парадокса в таблицах с 9 или более столбцами: присвоение первого значения NULL столбцу может занимать больше места на диске, чем записывать в него значение. И наоборот, при последнем столбце, не равном нулю, нулевая битовая карта отбрасывается для строки.

Физически исходная нулевая битовая карта занимает 1 байт между HeapTupleHeader (23 байта) и фактическими данными столбца или строкой OID (если вы все еще должны использовать это), что всегда начинать с кратного MAXALIGN (обычно 8 байт). Это оставляет 1 байт заполнения, который используется исходной нулевой битовой картой.

Фактически Хранилище NULL абсолютно бесплатно для таблиц из 8 столбцов или меньше.
После этого для следующих столбцов MAXALIGN * 8 выделяются еще MAXALIGN байты (обычно 8) (обычно 64). Etc.

Подробнее в руководстве и по этим связанным вопросам:

После того, как вы понимаете выравнивание элементов данных, вы можете дополнительно оптимизировать хранение:

Но случаи редки, когда вы можете сэкономить значительное количество места. Обычно это не стоит усилий.

@Daniel уже охватывает эффекты на размер индекса.

Ответ 2

Значения NULL попадают в индекс или не зависят, по крайней мере, от типа индекса. В основном это будет YES для btree и gist типов индексов НЕТ для hash, и кажется YES или NO для gin типов индексов в зависимости от версии PostgreSQL.

В таблице pg_catalog.pg_am использовался булевский столбец amindexnulls, который содержал эту информацию, но он был в 9.1. Вероятно, потому что индексы стали еще более сложными в улучшении PG.

В конкретном случае ваших данных лучшим способом было бы определить разницу в размерах индексов, используя функцию pg_relation_size('index_name'), между содержимым, полностью NULL и полностью NOT NULL, с вашей точной версией PG, точным типом данных, точный тип и определение индекса. И знайте, что, возможно, будущее изменение в любом из этих параметров может изменить исход.

Но в любом случае, если вы "просто" хотите избежать индексирования NULL, всегда можно создать частичный индекс:

CREATE INDEX partial_idx(col) ON table WHERE (col is not null)

Это займет меньше места, но зависит ли это от того, будет ли это отвечать или нет, зависит от этих запросов.