使用TDB的apache Jena中的Java OutOfMemoryError

使用TDB的apache Jena中的Java OutOfMemoryError,java,graph,rdf,jena,tdb,Java,Graph,Rdf,Jena,Tdb,您好,我一直在使用Jena进行一个项目,现在我正在尝试查询一个存储在普通文件中的图形,以便使用Hadoop进行批处理 我打开一个TDB数据集,然后按页面查询限制和偏移量 我输出的文件每个文件有100000个三元组 然而,在第10个文件中,性能下降,在第15个文件中,性能下降了3倍,在第22个文件中,性能下降到1% 我的问题是: 选择不同的S?p?O,其中{S?p?O.}限制100000个偏移量X 查询和写入文件的方法显示在下一个代码块中: public boolean copyGraphPage

您好,我一直在使用Jena进行一个项目,现在我正在尝试查询一个存储在普通文件中的图形,以便使用Hadoop进行批处理

我打开一个TDB数据集,然后按页面查询限制和偏移量

我输出的文件每个文件有100000个三元组

然而,在第10个文件中,性能下降,在第15个文件中,性能下降了3倍,在第22个文件中,性能下降到1%

我的问题是:

选择不同的S?p?O,其中{S?p?O.}限制100000个偏移量X

查询和写入文件的方法显示在下一个代码块中:

public boolean copyGraphPage(int size, int page, String tdbPath, String query, String outputDir, String fileName) throws IllegalArgumentException {
        boolean retVal = true;
        if (size == 0) {
            throw new IllegalArgumentException("The size of the page should be bigger than 0");
        }
        long offset = ((long) size) * page;
        Dataset ds = TDBFactory.createDataset(tdbPath);
        ds.begin(ReadWrite.READ);
        String queryString = (new StringBuilder()).append(query).append(" LIMIT " + size + " OFFSET " + offset).toString();
        QueryExecution qExec = QueryExecutionFactory.create(queryString, ds);
        ResultSet resultSet = qExec.execSelect();
        List<String> resultVars;
        if (resultSet.hasNext()) {
            resultVars = resultSet.getResultVars();
            String fullyQualifiedPath = joinPath(outputDir, fileName, "txt");
            try (BufferedWriter bwr = new BufferedWriter(new OutputStreamWriter(new BufferedOutputStream(
                    new FileOutputStream(fullyQualifiedPath)), "UTF-8"))) {
                while (resultSet.hasNext()) {
                    QuerySolution next = resultSet.next();
                    StringBuffer sb = new StringBuffer();
                    sb.append(next.get(resultVars.get(0)).toString()).append(" ").
                            append(next.get(resultVars.get(1)).toString()).append(" ").
                            append(next.get(resultVars.get(2)).toString());
                    bwr.write(sb.toString());
                    bwr.newLine();
                }
                qExec.close();
                ds.end();
                ds.close();
                bwr.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            resultVars = null;
            qExec = null;
            resultSet = null;
            ds = null;
        } else {
            retVal = false;
        }
        return retVal;
    }
内存查看器显示查询页面后内存使用的增量:

很明显,Jena LocalCache已满,我已将Xmx更改为2048m,将Xms更改为512m,结果相同。没有什么变化

我需要更多的记忆吗

我需要澄清什么吗

我需要停止程序并分部分执行吗

我的问题错了吗

偏移量和它有关系吗

我在一些旧邮件帖子中读到,你可以关闭缓存,但我找不到任何方法。有没有办法关闭缓存


我知道这是一个非常困难的问题,但我感谢任何帮助。

您似乎在某个地方出现内存泄漏,这只是一个猜测,但请尝试以下方法:

TDBFactory.release(ds);

REF:

您似乎在某处出现内存泄漏,这只是一个猜测,但请尝试以下方法:

TDBFactory.release(ds);
参考:

很明显,Jena LocalCache已满

这是TDB节点缓存-通常每个数据集本身需要1.5G 2G。此缓存在JVM的生命周期内持续存在

按照今天的标准,2G的java堆是一个小java堆。如果必须使用小堆,可以尝试在TDB中以称为直接模式的32位模式运行,但性能较差,主要原因是节点缓存较小,并且在此数据集中,确实有足够的节点导致小缓存的缓存搅动

节点缓存是堆耗尽的主要原因,但查询在其他位置(每个查询)以不同的方式消耗内存

这不一定便宜。它需要记住所看到的一切,以知道新行是第一次出现还是已经出现

ApacheJena确实优化了TopN查询的某些情况,但是 对于优化,默认值为1000。请参见代码中的OpTopN

否则,它将收集到目前为止看到的所有行。通过数据集的距离越远,节点缓存中的数据就越多,而DISTINCT过滤器中的数据也就越多

我需要更多的记忆吗

是的,再来一堆。合理的最小值是每个TDB数据集2G,然后是Java本身需要的任何值,比如0.5G,再加上您的程序和查询工作区

很明显,Jena LocalCache已满

这是TDB节点缓存-通常每个数据集本身需要1.5G 2G。此缓存在JVM的生命周期内持续存在

按照今天的标准,2G的java堆是一个小java堆。如果必须使用小堆,可以尝试在TDB中以称为直接模式的32位模式运行,但性能较差,主要原因是节点缓存较小,并且在此数据集中,确实有足够的节点导致小缓存的缓存搅动

节点缓存是堆耗尽的主要原因,但查询在其他位置(每个查询)以不同的方式消耗内存

这不一定便宜。它需要记住所看到的一切,以知道新行是第一次出现还是已经出现

ApacheJena确实优化了TopN查询的某些情况,但是 对于优化,默认值为1000。请参见代码中的OpTopN

否则,它将收集到目前为止看到的所有行。通过数据集的距离越远,节点缓存中的数据就越多,而DISTINCT过滤器中的数据也就越多

我需要更多的记忆吗


是的,再来一堆。合理的最小值是每TDB数据集2G,然后java本身需要的任何东西,比如说,0.5克,加上你的程序和查询工作空间。参见指南:如今2048万美元已经不是那么多了。为什么你不能简单地增加它?您使用的是哪一个Jena版本?@Nord,只是一个小评论:也许您不需要使用DISTINCT。@AKSW我使用的是2.14和3.4版本。这两个版本中的消息略有不同,但出现相同的错误。问题中的消息来自版本3.4。我删除了清晰的和增加的内存,我已经在第200页了。谢谢你的帮助。@Nord,图形是一组三元组。根据定义,图形没有重复项。但是为了消除结果的重复,你必须知道已经输出了什么,这可能是昂贵的。我认为你应该考虑重写这一点。参见指南:如今2048万美元已经不是那么多了。为什么你不能简单地增加它?你用的是哪一种耶拿版本?@Nord,只是一个小版本
t:也许您不需要使用DISTINCT。@AKSW我使用了版本2.14和3.4。这两个版本中的消息略有不同,但出现了相同的错误。问题中的消息来自版本3.4。我删除了清晰的和增加的内存,我已经在第200页了。谢谢你的帮助。@Nord,图形是一组三元组。根据定义,图形没有重复项。但要从结果中消除重复项,您必须知道已经输出的内容,这可能会很昂贵。在这种情况下,这不太可能有帮助,因为节点缓存将再次填满。每次都是相同的查询,以相同的顺序在数据库中执行不同的长度。在较长的查询中,节点缓存将以相同的方式填满,并在大约相同的点爆炸。在这种情况下,这不太可能有帮助,因为节点缓存将再次填满。每次都是相同的查询,以相同的顺序在数据库中执行不同的长度。在较长的查询中,节点缓存将以相同的方式填满,并在大约相同的点爆炸。谢谢,我看到了类似于您所描述的内容,我查询了第21页,它开始缓慢,也许我会删除DISTINCT,因为在hadoop mapper之后,reduce步骤将允许我检测重复项,当我到达主计算机时,我将使用4GB和6GB以及更高版本的12GB尝试您的解决方案。我将内存更改为4G并删除了DISTINCT,它运行正常。我将在MapReduce步骤中检查重复项。我认为2GB对于TDB的任何相关任务都足够了,但我在文档中没有找到它。谢谢。谢谢,我看到了与您描述的内容类似的内容,我查询了第21页,它的启动速度很慢,也许我会删除DISTINCT,因为在hadoop mapper之后,reduce步骤将允许我检测重复项,当我到达主计算机时,我将使用4GB和6GB以及更高版本的12GB尝试您的解决方案。我将内存更改为4G并删除了DISTINCT,它运行正常。我将在MapReduce步骤中检查重复项。我认为2GB对于TDB的任何相关任务都足够了,但我在文档中没有找到它。谢谢