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

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

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

Первый из моих рук. Однако я читал о втором.

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

Редактировать:
Вот код, где у меня есть функция, которая выполняет 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: вопрос может не хватать некоторых деталей. Если это так, пожалуйста, прокомментируйте, и я буду редактировать и добавлять их.

2

Решение

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

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

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

Также:

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

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

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

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

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

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

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

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]