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

问题描述:

在一个过程中,在服务器端使用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

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

  • 仅使用一个所有插入的交易,以及交易必须explicitally声明。如果未声明,则默认情况下会为每个插入创建一个新事务。

  • 创建一个且只有一个PreparedStatement的做所有的插入和重用它尽可能。

+0

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