【问题标题】:Most efficient multithreading Database Insert in JavaJava中最高效的多线程数据库插入
【发布时间】:2017-05-04 20:07:15
【问题描述】:

我们必须将大量数据从 HDD (~50GB) 读取到我们的数据库中,但是我们的多线程过程非常慢(~2h for ~10GB),因为org.sqlite.core.NativeDB.reset[native] 内部有一个线程锁(请参阅线程采样器)。

我们读取数据的速度相对较快,并使用我们的插入方法来执行准备好的语句。但只有当我们收集了 500.000 个数据集时,我们才会将所有这些语句提交到我们的数据库中。目前我们使用JDBC 作为sqlite 数据库的接口。

如果您总共使用一个线程,到目前为止一切正常。但是如果你想使用多个线程,你看不到性能/速度的提升,因为一次只能运行一个线程,而不是并行运行。 我们已经重用了我们的preparedStatement,并且所有线程都使用我们的数据库类的一个实例来防止文件锁定(与数据库有一个连接)。

不幸的是,我们不知道如何进一步改进我们的插入方法。有没有人能给我们一些提示/解决方案或如何不使用这个 NativeDB.reset 方法的方法? 我们不必使用 SQLite,但我们想使用 Java。

(线程被命名为 1,2,...,15)

private String INSERT = "INSERT INTO urls (url) VALUES (?);";

public void insert(String urlFromFile) {
  try {
    preparedStatement.setString(1, urlFromFile);
    preparedStatement.executeUpdate();
  } catch (SQLException e) {
    e.printStackTrace();
  }

}

按照@Andreas 的建议更新了插入方法,但它仍然抛出一些异常

public void insert(String urlFromFile) {
try {
  preparedStatement.setString(1, urlFromFile);
  preparedStatement.addBatch();
  ++callCounter;
  if (callCounter%500000 == 0 && callCounter>0){
    preparedStatement.executeBatch();
    commit();
    System.out.println("Exec");
  }
} catch (SQLException e) {
  e.printStackTrace();
}

}

java.lang.ArrayIndexOutOfBoundsException: 9
at org.sqlite.core.CorePreparedStatement.batch(CorePreparedStatement.java:121)
at org.sqlite.jdbc3.JDBC3PreparedStatement.setString(JDBC3PreparedStatement.java:421)
at UrlDatabase.insert(UrlDatabase.java:85)

【问题讨论】:

  • 我记得很清楚,SQLite 本身一次只允许一次操作。
  • @Andreas 我们存储所有插入,然后一次提交 500k。批处理没有带来重大改进:(
  • 您在插入之前删除了索引吗?
  • @YCF_L 我们将再次进行批处理,并提供我们的示例。谢谢!
  • 您是说批处理,即将executeUpdate() 替换为addBatch(),然后每1000 次以上调用executeBatch() 替换addBatch(),并不能提高性能?我发现这不太可能,除非您的性能瓶颈主要在其他一些领域,例如插入的表上的索引数量过多。提交间隔与它几乎没有关系。

标签: java database performance sqlite jdbc


【解决方案1】:

大多数数据库都有某种批量插入功能,尽管没有标准,AFAIK。

例如,Postrgresql 有 COPY,而 MySql 有 LOAD DATA。 不过,我认为 SQLite 不具备这种功能 - 可能值得切换到具备这种功能的数据库。

【讨论】:

【解决方案2】:

SQLitehas no write concurrency.

加载大量数据的最快方法是使用单个线程(和单个事务)将所有内容插入数据库(而不是使用 WAL)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多