Транзакция не может обрабатываться параллельно несколькими потоками со стандартным PostgreSQL до Postgres 9,6 , где эта функция была добавлена как "параллельный запрос" .
Однако кажется подозрительным, что ваша операция INSERT связана с процессором. Несколько вещей могут быть улучшены здесь. Как именно вы отправляете данные на сервер? Есть в основном четыре способа INSERT
данных в таблицу:
- по одной строке за раз с выражением
VALUES
, обеспечивающим литералы
- несколько строк одновременно
VALUES
выражение
INSERT
с SELECT
(вставка 0-n строк)
COPY
COPY
- самый быстрый метод на сегодняшний день.
Это быстрее удалить индексы перед массовым INSERT
/ COPY
и воссоздать их впоследствии. Постепенное добавление кортежей индекса гораздо менее эффективно, чем создание индекса сразу.
Триггеры, ограничения или ограничения внешнего ключа - это другие факторы, которые могут замедлить вас. Может быть, вы могли бы отключить / удалить до массовой загрузки, а затем включить / восстановить?
Существует также ряд настроек, которые могут существенно изменить ситуацию.
Прочтите статью о Массовая загрузка и восстановление и Настройка сервера PostgreSQL в Вики Postgres, особенно параграфы checkpoint_segments и checkpoint_completion_target .
Операция может быть не такой ограниченной, как кажется. Посмотрите на этот абзац в PostgreSQL Wiki .
Еще одним источником замедления может быть регистрация. Например, log_statement = all
создает огромные файлы журналов по цене, особенно с однострочными вставками.
Вот быстрый способ проверить все ваши пользовательские настройки в PostgreSQL Wiki еще раз.
Еще одна идея, чтобы ускорить процесс, тем более что вы не можете отключить fsync. Создайте одну или несколько пустых временных таблиц , например:
CREATE TEMP TABLE x_tmp AS SELECT * FROM real_tbl LIMIT 0;
Подумайте, как работать с последовательностями и другими значениями по умолчанию!
INSERT
все данные в промежуточные таблицы, затем записать в целевые таблицы одной командой. Индексы и ограничения снова отключаются, но на гораздо более короткое время.
INSERT INTO real_tbl SELECT * FROM x_tmp ORDER BY something;
DROP TABLE x_tmp;
Может быть значительно быстрее. Обязательно используйте достаточно оперативной памяти для различных настроек. В частности, обратите внимание на temp_buffers
.