2008-12-15 67 views
13

我正在寫一個程序,它會對Postgres數據庫進行大量寫入。在一個典型的場景中,我會寫100,000行到標準化很好的表(三個外部整數鍵,它們的組合是表的主鍵和索引)。我正在使用PreparedStatements和executeBatch(),但我只能在我的筆記本電腦上用約70秒鐘的時間推入100k行,當我們替換的嵌入式數據庫(具有相同的外鍵約束和索引) 10.關於加速JDBC寫入的提示?

我是JDBC新手,我不希望它擊敗一個自定義的嵌入式數據庫,但我希望它只有2-3倍慢,而不是7倍。任何明顯的,我可能會錯過?寫的順序是否重要? (也就是說,如果它不是索引的順序?)。要注意多擠一點速度?

+0

更新:我應該補充說,所有上述更新都是在一次交易中完成的,並且我試圖放棄這些指數,而沒有太大的影響(最多可以提高20%增加指數)。 – 2008-12-15 18:03:03

+0

什麼是您要替換的嵌入式數據庫? – systemoutprintln 2008-12-15 20:36:22

回答

8

這是我經常在當前項目中遇到的一個問題。對於我們的應用程序來說,插入速度是一個關鍵瓶頸。但是,我們發現絕大多數數據庫用戶的選擇速度是他們的主要瓶頸,所以你會發現有更多的資源處理這個問題。

因此,這裏是我們已經想出了幾個解決方案:

首先,所有的解決方案涉及使用Postgres的COPY command。使用COPY將數據導入到postgres是迄今爲止最快的方法。但是,默認情況下,JDBC驅動程序目前不支持網絡套接字中的COPY。所以,如果你想使用它,你將需要做兩個解決方法之一:

  1. 補丁支持COPY,比如這個one JDBC驅動程序。
  2. 如果要插入的數據與數據庫位於同一臺物理機器上,則可以將數據寫入文件系統中的文件,然後使用COPY命令批量導入數據。

提高速度的其他選擇是使用JNI來打postgres api,所以你可以通過unix套接字,刪除索引和pg_bulkload project。但是,如果你不實施COPY,你總會發現性能令人失望。

1

你可以明顯地試圖改變你的批量的大小,以找到適合您配置的最佳尺寸,但我懷疑,你將獲得一個因素3.

您也可以嘗試調整你的數據庫結構。使用單個字段作爲主鍵時,使用組合PK時可能會有更好的表現。根據您所需的完整性級別,您可以通過停用數據庫的完整性檢查來節省相當多的時間。

您也可能更改您正在使用的數據庫。 MySQL對於高速簡單插入應該是相當不錯的...我知道有一個MySQL的分支,它試圖削減功能以獲得高度併發訪問的高性能。

祝你好運!

1

嘗試禁用索引,並在插入後重新啓用它們。此外,在整個交易中包裝整個過程

2

檢查您的連接是否設置爲autoCommit。如果autoCommit爲true,那麼當您調用executeBatch時,如果批處理中有100個項目,則它將發出100個單獨的提交。這可能比調用executeBatch()後跟一個顯式提交()慢得多。

我會避免在插入過程中刪除索引或外鍵的誘惑。它使表在處於加載狀態時處於不可用狀態,因爲在索引不存在時,沒有人可以查詢表。此外,它看起來已經足夠無害,但是當您嘗試重新啓用約束時,您會做什麼,並且因爲您不希望發生的事情發生而失敗? RDBMS具有完整性約束是有原因的,甚至「暫時」禁用它們也是危險的。