从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驱动程序。
经过一些优化后,现在需要大约15秒来生成数据库。所有的研究和测试后,最重要的是thigs:
仅使用一个所有插入的交易,以及交易必须explicitally声明。如果未声明,则默认情况下会为每个插入创建一个新事务。
创建一个且只有一个PreparedStatement的做所有的插入和重用它尽可能。
你是对的,它显着提高了速度。 – user3473445 2018-01-13 19:28:26
1.显示您的Java代码。 2.显示你的SQLite模式。 – 2014-12-19 09:34:06
谢谢,我已经更新了答案。 – drublik 2014-12-19 09:48:29
mmm ...有时我不明白一些stackoverflow贡献者...为什么这个问题有倒票?我想知道改善它的原因。谢谢! – drublik 2014-12-19 09:49:12