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

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

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

3 ответа

Решение

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

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

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

По сути, NULL-хранилище абсолютно бесплатно для таблиц из 8 столбцов или менее.
После этого еще один MAXALIGN байты (обычно 8) выделяются для следующего MAXALIGN * 8 столбцы (обычно 64). И т.п.

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

Когда вы поймете, что выравнивание типов данных, вы можете оптимизировать хранилище:

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

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

Будь то NULL значения попадают в индекс или не зависят хотя бы от типа индекса. В основном это будет ДА для btree а также gist типы индекса, НЕТ для hashи кажется ДА или НЕТ для gin Типы индексов в зависимости от версии PostgreSQL.

Раньше был логический столбец amindexnulls в pg_catalog.pg_am таблица, которая несла эту информацию, но она ушла в 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)

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

Я считаю, что каждый будет использовать один бит в битовой карте для строки. Смотрите здесь: http://www.postgresql.org/docs/9.0/static/storage-page-layout.html

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