Занимают ли обнуляемые столбцы дополнительное пространство в 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). И т.п.
Более подробно в руководстве и по этим связанным вопросам:
- Сколько дискового пространства требуется для хранения значения NULL с использованием базы данных postgresql?
- Разве использование NULL в PostgreSQL все еще не использует растровое изображение NULL в заголовке?
- Сколько записей я могу хранить в 5 МБ PostgreSQL на Heroku?
Когда вы поймете, что выравнивание типов данных, вы можете оптимизировать хранилище:
Но случаи редки, когда вы можете сэкономить значительное количество места. Обычно это не стоит усилий.
@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