java - 将许多语句加载到 Jena 数据集中的最有效方法是什么?

标签 java transactions rdf jena bigdata

我正在使用 Jena TDB维护各种软件项目的调用依赖结构。在对大型项目进行静态分析后,我可能需要向 TDB 支持的数据集中的专用 Jena 模型添加 10 万条语句,在极端情况下甚至可能达到数百万条。

问题

添加 300k 语句大约需要 11 分钟。想象一下添加 3M 需要多长时间。 我想知道是否有另一种方法可以添加这么多语句,或者完全是另一种技术。

我尝试过的

  • 使用 model.add(List<Statement> stmts) 添加了所有语句- 抛出 java.lang.OutOfMemoryError并由于获得写锁而占用数据集。
  • 以 block 的形式添加所有语句,例如1000,同时提交和释放之间的锁。可以工作,但如上所述需要很长时间,我推测是由于事务性预写日志记录的开销。
  • 以非事务方式将语句添加到临时的、全新的和 TDB 支持的模型中,然后用新模型替换旧模型。 RAM 使用率急剧上升并降低了整个系统的速度。

附带问题

  • 对于这个用例,您是否会推荐 Jena/RDF 的替代品?
  • Jena 是否可以扩展 w.r.t.分布式文件系统/计算?

其他信息

我正在使用事务,这可能是由于繁重的 I/O 而导致的主要减速因素。但这无法避免,因为它是“一次交易,永远交易”。

A TDB-backed dataset can be used non-transactionally but once used in a transaction, it must be used transactionally after that.

感谢任何提示,非常感谢。


代码和测试

根据@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 ),但除此之外无论如何都不支持事务,我想必须防止数据集损坏。

最佳答案

Jena TDB 插入的成本很高,因为它会创建大量索引(或多或少是图、主语、谓语、宾语的所有组合)。重点是快速数据访问,而不是快速数据插入。

为了获得可接受的插入时间,我最终使用了 SSD。

至于替代方案,我可以指出:

  • 允许在数据库中选择所需索引的 RDF4J(以前称为 SESAME)。
  • Parliament ( http://parliament.semwebcentral.org/ ) 基于 Berkeley DB 作为 NoSQL 数据库后端,插入速度似乎相当快。

关于java - 将许多语句加载到 Jena 数据集中的最有效方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40584566/

相关文章:

java - Jersey REST 服务 - Tomcat 中的 404 响应

java - 一次有多个 FileOutputStream?

Mysql手动自增并发连接数证明

objective-c - 后退按钮上的 UINavigationController 自定义过渡动画

java - Camel 交易定界

java - 如何增加资源?

java - kafka消费者内存消耗高

java - 构建自定义 java 配置注释 - 类似于自定义 XML 命名空间

sparql - RDF - 一个主题属性的多个对象

sparql - 首选组合 SPARQL