GraphDB 查询无声地失败(OutOfMemoryError)

GraphDB queries fail silently (OutOfMemoryError)

我正在处理一个非常庞大的存储库(即 ~16M 语句)。我正在尝试获取图表中所有不同 class 成员模式的列表。这是查询:

PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>

select distinct (group_concat(?t) as ?fo)
where { 
    ?s rdf:type ?t.    
} 

group by (?s)
order by ?fo

当然这样的查询确实要return结果。奇怪的是,有时我会得到我需要的结果,有时查询 return 没有结果。

为什么会发生这种情况,我该如何避免?

PS: 监控查询,我注意到当我没有数据时,查询状态停留在:

IN_HAS_NEXT

0 operations

直到结论。

更新:

Here是描述问题的主要日志。 GraphDB workbench 中的输出是:

No results. Query took 1m 53s, minutes ago.

没有提到错误。很奇怪。正如 Gilles-Antoine Nys 指出的那样,这是内存和 Java 的 GC 的问题。总的来说,我认为 workbench 应该在这种情况下明确显示错误消息。

首先,您的查询无法为您提供可由类型定义的 class...为了表现力,我重新开始在您的 select 中添加 ?s。这样您就可以轻松回答您的问题了。

这是最简单的查询:

select ?s (group_concat(?t) as ?fo)
where { 
?s rdf:type ?t.    
} group by (?s)

order by(?fo)如果对你重要可以加)。

其次,IN_HAS_NEXT 只是您在监视器中暂停查询时的一种状态。与错误无关。

最后,验证您的 query-timeout 参数。它的默认值设置为 0。

更新:

实际上您的日志文件中有两个错误。问题是您的 JVM 对您的内存进行垃圾收集的时间太长(超过 98% 的内存仍在使用中)。

一个解决方案是增加您的 GC 开销限制,因此可以处理您的庞大数据集。

正如其他评论所说,错误是由 OME 引起的。在下一个即将发布的 GraphDB 8.6 版本中,开发人员实现了所有聚合和不同的内存效率更高的实现。在 public 发布之前,只有几个选项可供测试:

  1. 通过编写稍微更优化的查询版本来减少消耗的内存量,该版本仅显示本地名称:
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
select ?s_local (group_concat(?t_local) as ?fo)
where {
    ?s rdf:type ?t.
    BIND (REPLACE(STR(?t), "^(.*)(/|#)([^#/]*)$", "") as ?t_local)
    BIND (REPLACE(STR(?s), "^(.*)(/|#)([^#/]*)$", "") as ?s_local)
} group by (?s_local)
order by (?fo)
  1. 增加用于执行所有聚合计算的可用 RAM。您可以通过传递更高的 -Xmx 参数值或为 graphdb.properties 中的 graphdb.page.cache.size 设置最小数字来增加它,例如:graphdb.page.cache.size=100M。缓存控制存储在内存页面中的数量,这对于您的查询和存储库大小不会有太大影响。

  2. -Dgraphdb.engine.function.concat.max-length=4096限制组串的最大长度。该限制不会使查询成功执行,但会指示问题是否是主题太多太长的字符串。

GraphDB Free 的问题是:它会根据调用 workbench 增加堆大小。例如,如果您查询或只是刷新 workbench,您会看到堆大小增加。现在即使你有大量的内存,随着堆大小的不断增加,连续查询更多的查询也会产生 OOM。解决方案可能是在每次增加堆大小的调用中查找 GraphDB 存储的临时数据。