"Колонна тетриса"
На самом деле, вы можете сделать что-то , но это требует более глубокого понимания. Ключевое слово: отступ выравнивания . Каждый тип данных имеет особые требования к выравниванию .
Вы можете минимизировать пространство, потерянное для отступов между столбцами , упорядочив их. В следующем (крайнем) примере будет потрачено много физического дискового пространства:
CREATE TABLE t (
e int2 -- 6 bytes of padding after int2
, a int8
, f int2 -- 6 bytes of padding after int2
, b int8
, g int2 -- 6 bytes of padding after int2
, c int8
, h int2 -- 6 bytes of padding after int2
, d int8)
Чтобы сохранить 24 байта на строку, используйте вместо:
CREATE TABLE t (
a int8
, b int8
, c int8
, d int8
, e int2
, f int2
, g int2
, h int2) -- 4 int2 occupy 8 byte (MAXALIGN), no padding at the end
SQL Fiddle.
Как правило, если сначала поставить 8-байтовые столбцы, а затем 4-байтовые, 2-байтовые и 1-байтовые столбцы, вы не ошибетесь.
boolean
, uuid
и некоторые другие типы не требуют выравнивания. text
, varchar
и другие типы "varlena" (переменной длины) номинально требуют выравнивания "int" (4 байта на большинстве машин). Но на самом деле нет выравнивания выравнивания в формате диска (в отличие от RAM). Я проверен во многих тестах. В конце концов я нашел объяснение в примечании в исходном коде:
Обратите внимание, что мы допускаем нарушение номинального выравнивания при хранении "упакованных" варен;
Обычно вы можете сэкономить пару байтов на строку, в лучшем случае проиграв "столбец тетриса" . В большинстве случаев это не нужно. Но с миллиардами строк это может означать пару гигабайт легко.
Фактический размер столбца / строки можно проверить с помощью функции pg_column_size()
.
Некоторые типы занимают больше места в оперативной памяти, чем на диске (сжатый или «упакованный» формат). Вы можете получить более высокие результаты для констант (в формате RAM), чем для столбцов таблицы, когда тестируете одно и то же значение (или строку значений и строку таблицы) с pg_column_size()
.
Наконец, некоторые типы могут быть сжатыми или "поджаренными" (сохранены вне строки) или и тем, и другим.
Накладные расходы на кортеж (строку)
4 байта в строке для указателя элемента - без учета вышеуказанных соображений.
И как минимум 24 байта (23 + заполнение) для заголовка кортежа. Руководство по разметке страницы базы данных:
Существует заголовок фиксированного размера (занимающий 23 байта на большинстве машин),
за которым следует необязательное пустое растровое изображение, необязательное поле идентификатора объекта и
пользовательские данные.
Для заполнения между заголовком и пользовательскими данными вам необходимо знать MAXALIGN
на вашем сервере - обычно 8 байтов в 64-битной ОС (или 4 байта в 32-битной ОС). Если вы не уверены, проверьте pg_controldata
.
Запустите следующее в вашем двоичном каталоге Postgres , чтобы получить окончательный ответ:
./pg_controldata /path/to/my/dbcluster
Руководство:
Фактические данные пользователя (столбцы строки) начинаются со смещения
обозначено t_hoff
, которое всегда должно быть кратным MAXALIGN
расстояние до платформы.
Таким образом, вы обычно получаете оптимальный объем хранения, упаковывая данные в кратные 8 байт.
Ничего не получится в примере, который вы разместили . Это уже плотно упаковано. 2 байта заполнения после последнего int2
, 4 байта в конце. Вы можете объединить заполнение до 6 байтов в конце, что ничего не изменит.
накладные расходы на страницу данных
Размер страницы данных обычно составляет 8 КБ. Некоторые издержки / раздувание на этом уровне тоже: остатки недостаточно велики для размещения другого кортежа и, что более важно, мертвые строки или процент, зарезервированный с параметром FILLFACTOR
.
Существует несколько других факторов, влияющих на размер диска:
Типы массивов?
При использовании типа array , который вы оценивали, вы добавили бы 24 байта служебных данных для этого типа. Плюс, элементы массива занимают место как обычно. Нечего там приобретать.