【问题标题】:Create and import a big amount of data into a SQLite database from Java efficiently从 Java 高效地创建大量数据并将其导入 SQLite 数据库
【发布时间】:2015-01-09 19:56:50
【问题描述】:

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

  • 我的第一种方法是在内存中创建 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.显示您的 Java 代码。 2. 显示您的 SQLite 架构。
  • 谢谢,我已经更新了答案。
  • 嗯...有时我不明白一些stackoverflow贡献者...为什么这个问题有反对票?我想知道改进它的原因。谢谢!
  • 我不明白为什么这也有反对票
  • 使用一个准备好的语句在每个表中插入一行。

标签: java sqlite


【解决方案1】:

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

  • 对所有插入仅使用一个事务,并且必须显式声明事务。如果未声明,则默认为每次插入创建一个新事务。

  • 创建一个且仅一个 PreparedStatement 来执行所有插入操作并尽可能地重用它。

【讨论】:

  • 你是对的,它大大提高了速度。
猜你喜欢
  • 2016-04-14
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
  • 2015-04-19
  • 2019-02-22
  • 2021-05-19
  • 2011-09-21
  • 2015-11-19
相关资源
最近更新 更多