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

What's the most efficient way to load many statements into a Jena dataset?

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

问题

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

我试过的

附带问题

其他信息

我正在使用事务,这可能是由于繁重 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))

将堆 space 增加到 4GB 可以避免这个问题,但仍然占用数据集将近两分钟。

Statement count: 3233481
Transaction took 108.682 seconds.

使用 TDBLoader 很可能会以相同的方式表现(表示 here),但除此之外不支持交易,我想必须防止数据集损坏。

如果您正在使用事务,请使用一个事务来覆盖整个加载 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() ; 
 }

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

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

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

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

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

我在使用远程 Jena TDB 和 Fuseki 时遇到了同样的问题。我所做的是 posting(http post) 整个数据作为文件发送到远程 Jena Data 端点,即

http://FusekiIP:3030/yourdataset/data