Использование libpqxx для хранения данных навалом или использование оператора COPY в libpqxx

Чтобы вставить объемные данные / заполнить базу данных в PostgreSQL, самым быстрым способом будет использование COPY. Источник
Я должен заполнить базу данных. Сейчас я получаю скорость записи до 100-200 в секунду. Это связано с отправкой многих отдельных ВСТАВКИ через библиотеку libpqxx C ++. Я полагаю, что две причины:

  1. Данные имеют много повторных записей. (У меня есть сырые журналы, которые я разбираю и отправляю.) Это вызывает исключение первичного ключа.
  2. Посылка сообщений вставки по одному.

Первый из моих рук. Однако я читал о втором.
Насколько я знаю, класс tablewriter подходит для этой цели. Однако он, судя по всему, устарел. Я прочитал, что можно использовать stdin в качестве параметра для копирования.
Но после этих подсказок я проиграл. Может ли кто-нибудь привести меня к решению?

Edit: Вот код, где у меня есть функция, которая выполняет statemnt:

void pushLog(Log log,pqxx::connection *conn){ pqxx::work w(*conn); std::stringstream stmt; stmt<<"INSERT INTO logs VALUES('"<<log.getDevice()<<"','"<<log.getUser()<<"','"<<log.getDate()<<"','"<<log.getLabel()<<"');"; try{ pqxx::result res = w.exec(stmt.str()); w.commit(); } catch(const std::exception &e){ std::cerr << e.what() << std::endl; std::cout<<"Exception on statement:["<<stmt.str()<<"]\n"; return; } } 

Я устанавливаю соединение раньше и передаю ссылку на него.

PS: На вопрос может не хватать деталей. Если да, прокомментируйте, и я отредактирую и добавлю их.

Функция pushLog фиксирует каждую вставку отдельно, а фиксация выполняется медленно.

Как поясняется в документации по заполнению базы данных :

Если вы разрешаете каждую вставку отдельно, PostgreSQL выполняет большую работу для каждой добавленной строки

Также:

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

Однако в вашем случае это будет проблемой, а не выгодой, потому что каждый INSERT может выйти из строя при нарушении первичного ключа, тем самым отменив предыдущие INSERT с момента последнего фиксации. Обратите внимание, что это также будет проблемой с COPY , если вы используете это.

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

Обычно используются два метода:

  1. Избегайте ошибки: INSERT INTO... WHERE NOT EXISTS (SELECT 1 FROM table WHERE primary_key=...)

  2. Захватите ошибку, вставив внутри функцию plpgsql, у которой есть блок EXCEPTION, игнорирующий itr. Конкретные INSERT (ы), вызывающие дубликат, будут отменены, но транзакция не будет прервана.

Если у вас есть параллельные вставки, эти методы необходимо уточнить с помощью стратегии блокировки.