2013-10-30 71 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