从Java高效地创建大量数据并将其导入SQLite数据库

时间:2014-12-19 09:30:28

标签: java sqlite

在一个进程中,在使用Java的服务器端,我将创建一个SQLite数据库并导入大量数据(分为3个表中的1.200.000行)并让用户下载生成的数据库。

  • 我的第一个方法是在内存中创建SQLite数据库,执行所有插入,最后将数据库保存到磁盘。它有效,但它真的很慢。最多需要42秒。

  • 第一项改进是定义一项交易。如果我没有定义事务,SQLite会为每个插入创建一个,这很慢。对所有这些只进行一次交易,大约需要30秒。这对我们的情况来说还不够。

  • 第三种方法是做同样的事情,但不是一个接一个地调用executeUpdate执行每个插入,而是创建一个包含所有插入的StringBuffer,并使用一次调用executeUpdate将它们全部发送到一起。这稍微快一点,但只有2或3秒。

当我虽然没有办法更快地完成它时,我意识到使用sqlite命令行工具,我可以执行“.import csv_file tablename”并且它更快地导入数据,所以我可以导出我的数据到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驱动程序。

1 个答案:

答案 0 :(得分:1)

经过一些优化后,现在生成数据库大约需要15秒。在所有的研究和测试之后,最重要的是:

  • 对所有插入只使用一个事务,并且必须明确声明事务。如果未声明,则默认情况下会为每个插入创建一个新事务。

  • 创建一个且只有一个PreparedStatement来执行所有插入并尽可能地重复使用它。