要在 PostgreSQL 中插入批量数据/填充数据库,最快的方法是使用 COPY。Source https://stackoverflow.com/questions/758945/whats-the-fastest-way-to-do-a-bulk-insert-into-postgres
我必须填充数据库。现在我正在写入速度低至 100-200每秒。这涉及通过 C++ 库发送许多单独的插入libpqxx。我认为的两个原因是:
-
数据中有很多重复的记录。(我有原始日志,我会解析并发送这些日志。)这会导致主键异常。
- 插入语句的一一发送。
第一个是我无法控制的。然而我正在阅读第二个。
据我所知,tablewriter 类适合这个目的。但它显然已被弃用。我读到可以使用 stdin 作为复制参数。
但在这些线索之后我迷失了。有人可以引导我找到解决方案吗?
编辑:
这是代码,其中我有一个执行该语句的函数:
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:这个问题可能缺少一些细节。如果有的话,请评论,我会编辑并添加它们。
The pushLog
函数单独提交每个插入,并且提交速度很慢。
正如文档中所解释的填充数据库 http://www.postgresql.org/docs/current/interactive/populate.html:
如果允许单独提交每个插入,则 PostgreSQL 是
为添加的每一行做大量工作
Also:
在一个事务中进行所有插入的另一个好处是
如果一行的插入失败,则插入
到该点插入的所有行都将回滚,因此您不会
被部分加载的数据卡住
然而,在您的情况下,这将是一个问题而不是好处,因为每个 INSERT 可能会因主键违规而失败,从而取消自上次提交以来的先前 INSERT。
请注意,这也会出现问题COPY
,你应该使用它吗?
由于确实有必要将事务中的查询分组以提高性能,因此您需要以不中止事务的方式处理主键违规。
通常使用两种方法:
避免错误:INSERT INTO... WHERE NOT EXISTS (SELECT 1 FROM table WHERE primary_key=...)
通过插入具有忽略 itr 的 EXCEPTION 块的 plpgsql 函数来捕获错误。导致重复的特定 INSERT 将被取消,但事务不会中止。
如果您有并发插入,则需要使用锁定策略来改进这些方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)