Насколько ALTER SEQUENCE является дорогой операцией?

Имеется следующий sequence:

CREATE SEQUENCE some_seq START 100000;

и следующая таблица, которая его использует:

CREATE TABLE IF NOT EXISTS some_entities
(
    id        INTEGER PRIMARY KEY DEFAULT nextval('some_seq'),
    some_data TEXT    NOT NULL
);

Я хочу сделать оптимизацию генерации primary key при вставке новых сущностей пакетами. Для этого я хочу генерировать ключ прямо в коде (сделать аналог allocation size из Hibernate).

Принцип работы будет следующий:

  1. Делаю шаг инкремента в some_seq в 50 вместо 1.
  2. При вставке нового пакета делаю запрос nextval() к БД, получаю значение, и инкрементирую его прямо в коде. Если значение при инкрементации достигает 50, то я делаю ещё один запрос nextval() и продолжаю работать уже со вторым значением (это делается для того, чтобы не было пересечений по первичным ключам при параллельном обращении к базе данных).
  3. Вставляю новые сущности со сгенерированными первичными ключами.

Возникает следующий вопрос. Для такой реализации мне необходим следующий sequence:

CREATE SEQUENCE user_seq START 100000 INCREMENT 50;

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

Так вот, а что если я всегда буду пользоваться обычным sequence, а перед вставкой пакета выполнять операцию

ALTER SEQUENCE user_seq INCREMENT 50;

и после выполнения операции:

ALTER SEQUENCE user_seq INCREMENT 1;

Насколько ALTER SEQUENCE является дорогой операцией? Не убьёт ли он всю производительность от генерации первичных ключей в коде?


Ответы (1 шт):

Автор решения: Alexander Pavlov

Кэширование лучше включить на уровне Постгриса, тогда он при первом обращении будет выделять сессии диапазон значений, из которого сессия может тратить не обращаясь к базе

Два способа

create table t1 (
  id serial
);
alter sequence t1_id_seq CACHE 50; -- говорим Постгрису кэшировать 50 значений

или

create sequence ids as integer CACHE 50;  -- говорим Постгрису кэшировать 50 значений
create table t2 (
  id integer not null default nextval('ids')
)
→ Ссылка