我们必须将大量数据从HDD(~50GB)读入我们的数据库,但是由于org.sqlite.core.NativeDB.reset[native]
内部的线程锁定,我们的多线程程序非常慢(约2小时~10GB)(见线程采样器。)
我们相对快速地读取数据并使用insert方法执行预准备语句。但是,只有我们收集了500.000个数据集,我们才将所有这些语句提交到我们的数据库。目前,我们使用JDBC
作为sqlite
数据库的接口。
如果你总共使用一个线程,到目前为止一切正常。但是如果你想使用多个线程,你不会看到很多性能/速度增加,因为只有一个线程可以在时间运行,而不是并行运行。
我们已经重用了preparedStatement
,并且所有线程都使用Database类的一个实例来防止文件锁定(与数据库有一个连接)。
不幸的是,我们不知道如何进一步改进我们的插入方法。是否有人能够提供一些提示/解决方案或如何不使用此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)
答案 0 :(得分:1)
大多数数据库都有某种批量插入功能,但它没有标准,AFAIK。
例如,Postrgresql具有COPY,而MySql具有LOAD DATA。 我不认为SQLite有这个功能 - 可能值得切换到一个数据库。
答案 1 :(得分:0)
SQLite has no write concurrency。
加载大量数据的最快方法是使用单个线程(和单个事务)将所有内容插入到数据库中(而不是使用WAL)。