Вы можете проверить, являются ли индексы или ограничения PK / FK в базе данных действительно узким местом, выполнив следующие шаги:
1) Убедитесь, что данные вставлены в одну транзакцию (отключите автокоммит)
2) Удалите все индексы и создайте их заново после импорта данных (вы не можете отключить индекс)
DROP INDEX my_index;
CREATE INDEX my_index ON my_table (my_column);
3) Удалите или отключите ограничения PK / FK и заново создайте или повторно включите их после импорта данных. Вы можете пропустить проверку ограничений PK / FK во время импорта данных, не удаляя их с помощью
ALTER TABLE my_table DISABLE trigger ALL;
-- data import
ALTER TABLE my_table ENABLE trigger ALL;
Недостатком этого подхода является то, что ограничения PK / FK не проверяются для данных, которые были вставлены / обновлены, когда проверка была отключена. Конечно, ограничения PK / FK применяются и для существующих данных, когда вы воссоздаете их после импорта данных.
Вы также можете отложить проверку ограничений PK / FK до конца транзакции. Это возможно, если и только если ограничение PK / FK определено как deferrable (не по умолчанию):
ALTER TABLE my_table ADD PRIMARY KEY (id) DEFERRABLE INITIALLY DEFERRED;
START TRANSACTION;
-- data import
COMMIT; -- constraints are checked here
или
ALTER TABLE my_table ADD PRIMARY KEY (id) DEFERRABLE INITIALLY IMMEDIATE;
START TRANSACTION;
SET CONSTRAINTS ALL DEFERRED;
-- data import
COMMIT; -- constraints are checked here
EDIT:
Чтобы сузить причину проблемы, вы можете импортировать данные вместе с вашим приложением, создать дамп базы данных (с операторами вставки) и снова импортировать этот дамп базы данных. Это должно дать вам представление о том, сколько времени занимает простой импорт и каковы накладные расходы приложения.
Создайте дамп базы данных только для данных с операторами INSERT
(операторы COPY
будут быстрее, но ваше приложение также использует вставки, так что это лучше для сравнения):
pg_dump <database> --data-only --column-inserts -f data.sql
Снова создайте пустую схему базы данных и импортируйте данные (с базовой синхронизацией):
date; psql <database> --single-transaction -f data.sql > /dev/null; date
Может быть, вы сможете немного лучше разобраться в проблеме с этим.