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

时间:2016-11-14 08:29:54

标签: java transactions rdf jena bigdata

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

问题

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

我尝试了什么

  • 使用model.add(List<Statement> stmts)添加了所有语句 - 由于获取的写锁定而引发java.lang.OutOfMemoryError并占用数据集。
  • 以例如块的形式添加了所有语句。 1000,同时提交和释放锁定。如上所述,工作但需要永久,我认为由于事务性预写日志记录的开销。
  • 非事务性地将语句添加到临时的,新的和TDB支持的模型中,然后用新模型替换旧模型。 RAM的使用率过高,并使整个系统变慢。

附带问题

  • 您会为此用例推荐使用Jena / RDF的替代方案吗?
  • Jena是否可以扩展w.r.t.分布式文件系统/计算?

其他信息

我使用的交易可能是由于I / O繁重而导致的主要减速因素。但是,不能避免这种情况,因为它曾经是交易性的,总是交易性的,而且#34;

  

TDB支持的数据集可以非事务性使用,但一旦在事务中使用,必须在事务性之后使用

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

代码&amp;测试

根据@ 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),但除此之外不支持我希望防止数据集损坏的交易。

3 个答案:

答案 0 :(得分:2)

如果您正在使用事务,请使用一个事务来覆盖整个加载300k语句。 300k通常非常大(也不是3M),除非它有很多很多非常大的文字。

单个Model.add(Coillection)应该有效。

或从文件加载:

dataset.begin(ReadWrite.WRITE) ;
 try {
   RDFDataMgr.read(dataset, FILENAME);
   dataset.commit() ;
 } finally { 
   dataset.end() ; 
 }

还有一个用于离线加载的bulkloader。这是一个单独的计划tdbloader

没有Model.add(Collection) - 有一个Model.add(List)。把它放在事务循环中。

dataset.begin(ReadWrite.WRITE) ;
 try {
   dataset.getDefaultModel().add(...)
   dataset.commit() ;
 } finally { 
   dataset.end() ; 
 }

Jena 3.1.1中有一个新的API。 http://jena.apache.org/documentation/txn/txn.html

答案 1 :(得分:2)

Jena TDB插入成本很高,因为它创建了大量索引(或多或少都是图形,主题,谓词,对象的组合)。重点是快速数据访问,而不是快速插入数据。

我最终使用SSD才能获得可接受的插入时间。

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

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

答案 2 :(得分:0)

我在远程Jena TDB和Fuseki上遇到了同样的问题。我所做的是将整个数据作为文件发布(http发布)到远程Jena Data端点

  

http://FusekiIP:3030/yourdataset/data