我正在使用neo4j存储有关电影评分的数据。我想计算两个用户都评分的电影数量。运行查询
match (a:User)-[:RATED]->(b:Movie)<-[:RATED]-(c:User) return a,b,c limit 1000
它在不到一秒钟的时间内完成,但是运行
match (a:User)-[:RATED]->(b:Movie)<-[:RATED]-(c:User) return a,count(b),c limit 1000
数据库无法完成查询,因为堆耗尽了内存,我将其设置为4GB。我是否正确使用计数功能?我不明白这两个查询之间的性能如何有很大差异。
失踪者对正在发生的事情有很好的解释。当您进行聚合时,必须考虑整个集合可以正确执行聚合,并且必须在限制之前发生,这对您的堆空间造成了巨大的损失。
在您的情况下,您可以尝试以下内容:
match (a:User)-[:RATED]->()<-[:RATED]-(c:User)
with DISTINCT a, c
where id(a) < id(c)
limit 1000
match (a)-[:RATED]->(m:Movie)<-[:RATED]-(c)
with a, c, count(m) as moviesRated
return a, moviesRated, c
通过在聚合之前移动限制,但使用独特的方式来确保我们只处理此模式中的一对节点(并根据图ID应用谓词,以确保我们永远不会处理镜像结果(,我们,我们应该得到更有效的查询。然后,对于1000对A和C中的每对,我们再次扩展模式并获得实际计数。
我遇到了类似的情况,并使用以下方法解决了这一点,这将适用于您。
我使用的数据集的数据集:(type_s(-380节点(type_n(-800000节点[:S_REALATION_N] -5600000关系
查询一个:
match (s:TYPE_S)-[]-(n:TYPE_N) return s, n limit 10
这取了2毫米。
在DB中发现了10种模式(关系(后,Neo4J刚刚返回结果。
查询两个:
match (s:TYPE_S)-[]-(n:TYPE_N) return s, sum(n.value) limit 10
这花了〜4000毫米。
这看起来像是最后一个查询。但是肯定的是,由于涉及的聚合,它不会像前一个一样快。
原因:
要查询要汇总模式,neo4j必须加载匹配给定模式的所有路径(这些路径超过10或在这里给定的限制,并且根据我的数据集将为5600000(,然后在执行聚合之前,将其列入RAM。稍后,此聚合将在10个完整记录S_TYPE节点上执行,因此现在将其属于指定的返回格式,现在具有给定的限制。然后,公羊中的其余关系被冲洗。这意味着片刻的运行装有批次数据,以后由于限制而忽略。
因此,要优化运行时间和内存使用量,您必须避免部分查询,这会导致加载数据,后来将被忽略。
这就是我优化它的方式:
match (s:TYPE_S) where ((s)-[]-(:TYPE_N))
with collect(s)[0..10] as s_list
unwind s_list as s
match (s)-[]-(n:TYPE_N) return s, sum(n.value)
这花费了64毫米。
现在,Neo4J首先入围10个类型的节点,它们与type_s有关系,然后与这些节点匹配模式并获取数据。由于您将有限的记录加载到RAM中,所以这应该比Query2起作用并运行得更好。
您可以通过缩短1000(a,b(不同的用户对,然后对其进行聚合来构建查询。但是,如果需要通过聚合订购的情况。
,这种方法将失败。您查询记忆的原因是因为您使用的是4 GB RAM并运行可能将大量组合数据加载到RAM中的查询(有时可能是您的DB大小,因此数据组合的多样性在您的模式中定义,即使您有50个唯一用户,您也有50*49个可能的模式组合,可以加载到RAM中(。另外,其他与并行运行的交易和查询也可能影响。