【发布时间】:2016-11-14 08:29:54
【问题描述】:
我正在使用Jena TDB 来维护各种软件项目的调用依赖结构。在对大型项目进行静态分析后,我可能需要将 100k 语句添加到 TDB 支持的数据集中的专用 Jena 模型中,在极端情况下可能甚至数百万。
问题
添加 300k 语句大约需要 11 分钟。想象一下添加 3M 需要多长时间。 我想知道是否有其他方法可以添加这么多语句,或者完全使用其他技术。
我尝试过的
- 添加了所有使用
model.add(List<Statement> stmts)的语句 - 抛出java.lang.OutOfMemoryError并由于获得的写锁而占用数据集。 - 以块的形式添加了所有语句,例如1000,同时在两者之间提交和释放锁。工作,但如上所述,我认为是由于事务性预写日志记录的开销。
- 以非事务方式将语句添加到临时、新鲜和 TDB 支持的模型中,然后用新模型替换旧模型。 RAM 使用率急剧上升,并降低了整个系统的速度。
附带问题
- 您是否会为此用例推荐 Jena/RDF 的替代品?
- Jena 是否可以缩放 w.r.t.分布式文件系统/计算?
其他信息
我正在使用事务,这可能是由于大量 I/O 而导致的主要减速因素。但无法避免这种情况,因为它是“一次交易,总是交易”。
TDB 支持的数据集可以非事务性使用,但一旦在事务中使用,之后必须以事务性方式使用。
感谢任何提示,非常感谢。
代码和测试
根据@AndyS 的建议,我重新尝试在单个事务中添加所有语句,如下所示:
List<Statement> statements = ...;
//Print statistics
System.out.println("Statement count: " + statements.size());
//Log the start of the operation to measure its duration
Long start = System.currentTimeMillis();
//Add all statements in one transaction
workspace.beginTransaction(ReadWrite.WRITE); //forwards to dataset.begin(ReadWrite rw)
try {
model.add(statements);
} catch (Exception e) {
e.printStackTrace();
workspace.abortTransaction(); //forwards to dataset.abort()
} finally {
workspace.commitTransaction(); //forwards to dataset.commit()
}
//Check how long the operation took
double durationS = (System.currentTimeMillis() - start) / 1000.0;
System.out.println("Transaction took " + durationS + " seconds.");
这是输出:
Statement count: 3233481
此事务运行的线程在调试器中崩溃并显示以下消息:
Daemon Thread [ForkJoinPool-1-worker-1] (Suspended (exception OutOfMemoryError))
将堆空间增加到 4GB 可以规避此问题,但仍会占用数据集近两分钟。
Statement count: 3233481
Transaction took 108.682 seconds.
使用TDBLoader 很可能会以相同的方式运行(表示为here),但除此之外不支持我希望防止数据集损坏的事务。
【问题讨论】:
-
JDWP exit error是一种平台系统错误 - 它与耶拿无关。有很多谷歌热。
标签: java transactions rdf jena bigdata