从Neo4j加载9M行并将其写入CSV会引发内存不足异常

从Neo4j加载9M行并将其写入CSV会引发内存不足异常,neo4j,spring-data-neo4j,spring-data-neo4j-4,neo4j-ogm,Neo4j,Spring Data Neo4j,Spring Data Neo4j 4,Neo4j Ogm,我有一个大图模型,我需要将下面的查询结果写入csv Match (u:USER)-[r:PURCHASED]->(o:ORDER)-[h:HAS]->(i:ITEM) return u.id as userId,i.product_number as itemId 当我“解释”查询时,我得到的结果是: 结果表明,估计结果约为900万。我的问题是: 1) 得到答复需要很长时间。从neo4j外壳开始需要38分钟!这正常吗?顺便说一句,我有所有模式索引,它们都在线 2) 当我使用Spr

我有一个大图模型,我需要将下面的查询结果写入csv

Match (u:USER)-[r:PURCHASED]->(o:ORDER)-[h:HAS]->(i:ITEM) return u.id as userId,i.product_number as itemId
当我“解释”查询时,我得到的结果是:

结果表明,估计结果约为900万。我的问题是:

1) 得到答复需要很长时间。从neo4j外壳开始需要38分钟!这正常吗?顺便说一句,我有所有模式索引,它们都在线

2) 当我使用SpringDataNeo4j获取结果时,它抛出一个“java.lang.OutOfMemoryError:超出GC开销限制”错误,当SDN尝试将加载的数据转换为@QueryResult对象时,就会发生这种情况

我试图以各种不同的方式优化查询,但没有任何改变!我的印象是我做错了什么。有人知道我如何解决这个问题吗?我应该批量读/写吗

另外,我使用的是Neo4j comunity版本:3.0.1,以下是我的系统信息:

这些是我的服务器配置

dbms.jvm.additional=-Dunsupported.dbms.udc.source=tarball
use_memory_mapped_buffers=true
neostore.nodestore.db.mapped_memory=3G
neostore.relationshipstore.db.mapped_memory=4G
neostore.propertystore.db.mapped_memory=3G
neostore.propertystore.db.strings.mapped_memory=1000M
neostore.propertystore.db.index.keys.mapped_memory=500M
neostore.propertystore.db.index.mapped_memory=500M

尽管Neo4j会在匹配结果时将结果流式传输给您,但当您使用SDN时,它必须将输出收集到单个
@QueryResult
对象中。为了避免OOM问题,您需要确保应用程序有足够的堆内存来加载所有9m响应,或者使用neo4j shell,或者使用专门构建的流接口,例如。(注意:我还没有尝试过这个,但看起来应该可以了)

您的配置设置对于Neo4j 3.0.1不正确

您必须在conf/neo4j-wrapper.conf中设置堆,例如8G

和conf/neo4j.conf中的页面缓存(查看您的商店,页面缓存只需要2G)

正如您所见,它将创建800多万行

您可能会更幸运地使用此查询:

Match (u:USER)-[:PURCHASED]->(:ORDER)-[:HAS]->(i:ITEM) 
with distinct u,i
return u.id as userId,i.product_number as itemId
老实说,将800万行返回给neoj shell也没有意义。 如果要测量它,请将
返回值
替换为
并添加
返回计数(*)

另一个优化<强>可以通过项目和用户进行,并在中间为“强”全局查询< /强>进行哈希连接:

Match (u:USER)-[:PURCHASED]->(o:ORDER)-[:HAS]->(i:ITEM) 
USING JOIN ON o
with distinct u,i
WITH u.id as userId,i.product_number as itemId
RETURN count(*)
为了减少返回结果的数量,我可能会做的另一件事是尝试聚合

Match (u:USER)-[:PURCHASED]->(o:ORDER)-[:HAS]->(i:ITEM)
with distinct u,i
WITH u, collect(distinct i) as products
WITH u.id as userId,[i in products | i.product_number] as items
RETURN count(*)

多亏文斯和迈克尔的评论,我找到了解决办法! 在做了一些实验之后,很明显服务器的响应时间实际上是很好的!900万数据只需1.5分钟!正如文斯所说,问题在于SDN!当SDN试图将数据转换为@QueryResult对象时,会发生OOM。为我们的应用程序增加堆内存并不是一个永久的解决方案,因为我们将来会有更多的行!因此,我们决定使用Neo4jJDBC驱动程序进行大数据查询它像喷气式飞机一样工作!下面是我们使用的代码示例:

Class.forName("org.neo4j.jdbc.Driver");
    try (Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://HOST:PORT", "USER", "PASSWORD")) {

        // Querying
        String query = "match (u:USER)-[r:PURCHASED]->(o:ORDER)-[h:HAS]->(i:ITEM) return u.id as userId,i.product_number as itemId";
        con.setAutoCommit(false); // important for large dataset
        Statement st = con.createStatement();
        st.setFetchSize(50);// important for large dataset

            try (ResultSet rs = st.executeQuery(query)) {
                while (rs.next()) {
                    writer.write(rs.getInt("userId") + ","+rs.getInt("itemId"));
                    writer.newLine();
                }

            }

        st.setFetchSize(0);
        writer.close();
        st.close();

    }

如果知道要加载大型数据集,请确保使用“con.setAutoCommit(false);”和“st.setFetchSize(50)”。谢谢大家

谢谢Michael,你说得对,dbms.memory.pagecache.size设置在错误的文件中。我改了。关于返回结果的数量,我不想减少它们,我需要它们全部。我需要创建一个csv的用户ID,项目ID。。。无法使用任何分组。。。我尝试了您建议的所有查询(vi neo4j shell…)都有相同的响应时间。我认为我的数据没有真正标准化:-),但我需要所有的副本。谢谢文斯,你给了我一个关于@QueryResult的好提示!
Class.forName("org.neo4j.jdbc.Driver");
    try (Connection con = DriverManager.getConnection("jdbc:neo4j:bolt://HOST:PORT", "USER", "PASSWORD")) {

        // Querying
        String query = "match (u:USER)-[r:PURCHASED]->(o:ORDER)-[h:HAS]->(i:ITEM) return u.id as userId,i.product_number as itemId";
        con.setAutoCommit(false); // important for large dataset
        Statement st = con.createStatement();
        st.setFetchSize(50);// important for large dataset

            try (ResultSet rs = st.executeQuery(query)) {
                while (rs.next()) {
                    writer.write(rs.getInt("userId") + ","+rs.getInt("itemId"));
                    writer.newLine();
                }

            }

        st.setFetchSize(0);
        writer.close();
        st.close();

    }