2013-10-30 31 views
2

要在PostgreSQL中插入批量数据/填充数据库,最快的方法是使用COPY。 Source
我必须填充数据库。现在我得到了写入速度低至每秒100-200。这涉及通过C++库libpqxx发送许多单独的INSERTS。这两个原因,我想主要有:使用libpqxx批量存储数据或如何在libpqxx中使用COPY语句

  1. 数据有许多重复的记录。(我有原始日志,我解析并发送。)这导致主键异常。
  2. 插入语句的逐个发送。

第一个不在我的手中。不过,我正在读第二本。
据我所知,tablewriter类适合这个目的。但它显然已被弃用。我读过可以使用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:这个问题可能缺少一些细节。如果是这样,请评论,我将编辑并添加它们。

+0

检查您是否没有为每个插入事件启动新的事务。你应该在一次交易中完成所有这些工作。如果可能,请显示相关的代码。 –

+0

@DanielVérité我添加了我的代码。我怀疑它发生在一个事务中,但是我不知道如何使用libpqxx控制事务。 – digvijay91

+0

是的,这段代码提交每个INSERT,这是不好的。您希望重新构建它只为循环中的每一行执行'w.exec(..)',并在此循环之外具有'pqxx :: work'实例化和'w.commit()'。 –

回答

1

pushLog函数分别提交每个插入,并且提交较慢。

If you allow each insertion to be committed separately, PostgreSQL is doing a lot of work for each row that is added

另外:

如文档的Populating a Database解释

An additional benefit of doing all insertions in one transaction is that if the insertion of one row were to fail then the insertion of all rows inserted up to that point would be rolled back, so you won't be stuck with partially loaded data

然而,在你的情况,这将是一个问题,而不是一个好处,因为每个插件可以在主键失败违规,从而取消自上次提交以来的先前INSERT。 请注意,这也可能是COPY的问题,如果您使用它。

由于确实需要将事务中的查询分组以进行性能分析,因此您需要以不中止事务的方式处理主键违例。

两种方法通常用于:由具有异常块忽略ITR一个PLPGSQL函数内部插入INSERT INTO... WHERE NOT EXISTS (SELECT 1 FROM table WHERE primary_key=...)

  • 捕获错误:

    1. 避免错误。导致重复的具体INSERT(s)将被取消,但事务不会中止。

    如果您有并发插入,则需要使用锁定策略对这些方法进行优化。

  • +0

    并发插入每个连接或跨所有连接?换句话说,如果一个事务是在'commit'之前建立在一个具有多个'exec'的连接上的,那么它们是否会干扰另一个使用另一个连接在另一个表上执行相同操作的连接?提前感谢你! – 2014-04-12 03:51:14

    +1

    @Gracchus:在同一连接中,并发插入是不可能的。在各种关系中,是的,只要他们争夺锁定,他们就会干涉。例如,如果目标表有一个主要键,则会使第二个插入事务等待,直到第一个提交。 –

    +0

    非常感谢您清除DanielVérité!这是否意味着第二笔交易将失败或将无限期推迟?非常非常非常感谢你! – 2014-04-12 14:00:10