{"id":14279,"url":"\/distributions\/14279\/click?bit=1&hash=4408d97a995353c62a7353088166cda4ded361bf29df096e086ea0bbb9c1b2fc","title":"\u0427\u0442\u043e \u0432\u044b\u0431\u0435\u0440\u0435\u0442\u0435: \u0432\u044b\u0435\u0445\u0430\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0438\u043b\u0438 \u0437\u0430\u0435\u0445\u0430\u0442\u044c \u0440\u0430\u043d\u044c\u0448\u0435?","buttonText":"","imageUuid":""}

PostgreSQL – быстрая вставка

Если нужно сделать быструю вставку, чтобы не держать транзакцию, то можно использовать промежуточную табличку или PgQ. Далее job (pgpro_scheduler) или сторонний worker может спокойно перекладывать данные (или оправлять куда-то, например в брокер сообщений) уже в другой транзакции.

В случае с собственной табличкой помните – вставку замедляет все: триггеры, индексы, ограничения, поля с AUTO_INCREMENT. Поэтому, чем меньше всего этого будет навешано, тем быстрее произойдет вставка.

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

CREATE TABLE transit ( message json NOT NULL );

Worker будет перекладывать данные в целевую таблицу с «обвесом», примерно так …

WITH transit AS ( DELETE FROM transit RETURNING * ) INSERT INTO target (message) SELECT message FROM transit;

Если нужно перенести не все записи, а пачку, например 1000 шт., то так …

WITH transit AS ( DELETE FROM transit WHERE ctid IN (SELECT ctid FROM transit LIMIT 1000) RETURNING * ) INSERT INTO target (message) SELECT message FROM transit; * ctid – системное поле.

Если нужно гарантированно повторить последовательность записи данных, то так …

CREATE TABLE transit ( id bigserial PRIMARY KEY, message json NOT NULL ); WITH transit AS ( DELETE FROM transit WHERE id IN (SELECT id FROM transit ORDER BY id) RETURNING * ) INSERT INTO target (message) SELECT message FROM transit ORDER BY id;
0
Комментарии
-3 комментариев
Раскрывать всегда