Фиксированный тип хранения ASCII? - PullRequest
0 голосов
/ 27 февраля 2020

У меня есть база данных, в которой необходимо хранить значения UN / LOCODE, и я обнаружил, что при использовании стандартных типов данных невозможно сохранить эти значения в форме фиксированного размера, чтобы я мог эффективно воспроизводить столбцы тетрис.

В настоящее время я определил для него домен следующим образом:

-- city: UN/LOCODE https://service.unece.org/trade/locode/Service/LocodeColumn.htm#LOCODE
CREATE DOMAIN t_locode AS VARCHAR
    CONSTRAINT t_locode_check CHECK (
        value IS NULL
        OR
        value ~ '^[A-Z]{2} [A-Z][A-Z0-9]{1,2}$'
);

... что приводит к:

testing=# \dT+ t_locode 
List of data types
-[ RECORD 1 ]-----+---------
Schema            | public
Name              | t_locode
Internal name     | t_locode
Size              | var
Elements          | 
Owner             | postgres
Access privileges | 
Description       | 

Я также пытался использовать фиксированный определение типа символа длины вместо VARCHAR (например, CHAR(6)), но это совсем ничего не меняет, что я подозреваю, потому что сама база данных установлена ​​в UTF-8, который по определению является символом переменной длины encoding.

Чтобы еще больше способствовать этой проблеме, этот домен затем используется в других пользовательских типах данных.

В лучшем случае я хотел бы определить тип данных, который может хранить эти значения, используя Максимум 8 байт для выравнивания с двойным.

Кто-нибудь знает решение для этого?

1 Ответ

1 голос
/ 27 февраля 2020

Строковые типы данных всегда типы данных переменной ширины в PostgreSQL, независимо от того, используете ли вы text, character varying или character.

Я думаю, что вы пытаясь оптимизировать то, что не нуждается в оптимизации. Такие попытки часто приносят больше вреда, чем пользы.

Если ваши строки всегда имеют длину 6 символов ASCII, они будут занимать 7 байт в хранилище:

CREATE TABLE x(id bigint, t text);

INSERT INTO x VALUES (1, '      '), (2, '000000');

CREATE EXTENSION pageinspect;

SELECT t_ctid, t_attrs FROM heap_page_item_attrs(get_raw_page('x', 0), 'x');

 t_ctid |                   t_attrs                   
--------+---------------------------------------------
 (0,1)  | {"\\x0100000000000000","\\x0f202020202020"}
 (0,2)  | {"\\x0200000000000000","\\x0f303030303030"}
(2 rows)

Это машина с прямым порядком байтов, как видно из столбца bigint.

Вы заметите, что значения text занимают всего 7 байтов каждое. Это вызвано TOAST , который является вашим другом, а не вашим врагом:

TOAST узурпирует два бита слова длины varlena (старшие биты на машинах с прямым порядком байтов) (младшие биты на машинах с прямым порядком байтов), что ограничивает логический размер любого значения типа данных с поддержкой TOAST до 1 ГБ (2 30 - 1 байт). [...] Когда установлен бит самого высокого порядка или самого низкого порядка, значение имеет только однобайтовый заголовок вместо обычного четырехбайтового заголовка, а оставшиеся биты этого байта дают общий размер данных (включая длина байта) в байтах.

0x0F является двоичным 00001111: самый правый 1 говорит, что у нас есть только однобайтовый заголовок, а оставшиеся 0000111 (десятичное число 7) являются длиной элемента данных, включая заголовок.

Поскольку ваши значения имеют длину всего 7 байтов, они будут хорошо выровнены с double precision с потерянным только одним байтом заполнения.

Если вы хотите для микрооптимизации, избегая байтов заполнения, поместите все строковые столбцы рядом друг с другом в конце определения таблицы. С другой стороны, учтите, что PostgreSQL должен пройти go по первым девяти столбцам, чтобы попасть в десятый столбец, поэтому размещение часто используемых столбцов на первом месте приведет к повышению производительности.

Но я бы не стал Слишком много беспокойства по поводу этих проблем: сохранение 4 байтов с использованием integer вместо bigint может вызвать большие проблемы позже, если вы поймете, что вам нужны большие числа, и размещение столбцов не имеет значения по сравнению с хорошей моделью данных, хорошо запрашивает и исправляет индексы, когда дело доходит до производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...