2014-12-19 402 views
1

在一個過程中,在服務器端使用Java,我必須創建一個SQLite數據庫並導入大量數據(分爲1.200.000行3個表),並讓用戶下載生成的數據庫。從Java高效地創建大量數據並將其導入SQLite數據庫

  • 我的第一種方法是在內存中創建SQLite數據庫,執行所有插入操作,最後將數據庫保存到磁盤。它可以工作,但速度很慢。它需要長達42秒。

  • 第一個改進是定義一個事務。如果我沒有定義事務,SQLite爲每個插入創建一個,並且這很慢。只爲他們做一筆交易,大約需要30秒。這對我們的案例來說還不夠。

  • 第三種方法是執行相同的操作,但不是逐個執行每個插入的調用executeUpdate,而是使用所有插入創建一個StringBuffer,並使用一次調用executeUpdate將它們全部發送到一起。這個速度稍快,但只有2或3秒。

當我雖然說沒有任何辦法做得更快,我意識到,與sqlite的命令行工具,我可以執行「.IMPORT csv_file表名」,它更快導入數據,所以我可以將我的數據導出到CSV文件,然後使用該工具導入它們。不過,我寧願不必從Java代碼中調用任何命令行工具,但我還沒有找到任何方法使用JDBC驅動程序執行相同的導入。所以我的問題是:

  • 你知道有什麼辦法做同樣的CSV導入命令行工具從Java代碼嗎?

  • 您是否有更好的方法來創建SQLite數據庫並以高效的方式導入大量數據?

編輯:代碼& SQLite的模式:

我不能顯示完整的架構定義,但也有在3個表如下:

CREATE VIRTUAL TABLE xxxxx USING rtree(...) with 5 attributes. 
CREATE VIRTUAL TABLE xxxxx USING fts3 (...) with 1 attribute. 
CREATE TABLE poidata(xxxxx) with 15 attributes. 

沒有在表之間的任何外鍵,並且沒有任何索引除了PK之外。

關於代碼,很簡單。我生成一個StringBuffer所有的刀片,最後我執行:

Statement st = this.getConnection().createStatement(); 
st.execute("begin transaction"); 
st.executeUpdate(sql.toString()); 
st.execute("end transaction"); 
st.executeUpdate("backup to " + destination.getAbsolutePath()); 

我目前使用的SQLite的Xerial JDBC驅動程序。

+0

1.顯示您的Java代碼。 2.顯示你的SQLite模式。 – 2014-12-19 09:34:06

+0

謝謝,我已經更新了答案。 – drublik 2014-12-19 09:48:29

+0

mmm ...有時我不明白一些stackoverflow貢獻者...爲什麼這個問題有倒票?我想知道改善它的原因。謝謝! – drublik 2014-12-19 09:49:12

回答

1

經過一些優化後,現在需要大約15秒來生成數據庫。所有的研究和測試後,最重要的是thigs:

  • 僅使用一個所有插入的交易,以及交易必須explicitally聲明。如果未聲明,則默認情況下會爲每個插入創建一個新事務。

  • 創建一個且只有一個PreparedStatement的做所有的插入和重用它儘可能。

+0

你是對的,它顯着提高了速度。 – user3473445 2018-01-13 19:28:26

相關問題