簡體   English   中英

有效地從Java創建大量數據並將其導入SQLite數據庫

[英]Create and import a big amount of data into a SQLite database from Java efficiently

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

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

  • 第一項改進是定義一個事務。 如果我沒有定義事務,SQLite會為每個插入創建一個事務,這很慢。 僅對所有這些進行一次事務,大約需要30秒。 對於我們的情況而言,這還不夠。

  • 第三種方法是執行相同的操作,而不是一個一個地調用executeUpdate來一次執行每個插入,而是創建一個包含所有插入的StringBuffer,並僅使用一次對executeUpdate的調用將它們一起發送。 這稍微快一點,但是只有2或3秒。

當我沒有辦法更快地執行此操作時,我意識到使用sqlite命令行工具可以執行“ .import csv_file表名”,並且可以更快地導入數據,因此可以將數據導出到CSV文件,然后使用該工具將其導入。 但是,我希望不必從Java代碼中調用任何命令行工具,但是我還沒有找到使用JDBC驅動程序執行相同導入的任何方法。 所以我的問題是:

  • 您是否知道通過命令行從Java代碼執行相同的CSV導入的任何方法?

  • 您是否有更好的方法來創建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());

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

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

  • 所有插入僅使用一個事務,並且必須顯式聲明該事務。 如果未聲明,默認情況下它將為每個插入創建一個新事務。

  • 創建一個並且只有一個PreparedStatement可以完成所有插入操作,並盡可能地重用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM