【发布时间】: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。
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