【问题标题】:Neo4j expand query is very slowNeo4j 扩展查询很慢
【发布时间】:2017-12-30 08:49:06
【问题描述】:

我用的是neo4j-community-3.3.0,会有:

  • 节点数:20000,
  • 关系:72000,
  • 每个节点的属性:1,
  • 属性 per_relationship:1

我的机器有:

  • 内存:16G,
  • dbms.memory.pagecache.size:6G,
  • dbms.memory.heap.max_size:8G

我想将所有节点连接到一个节点并汇总与这些节点相关的关系属性并将结果发送到 csv 文件。我想对数据库中的所有节点执行此操作。

我有一个关于关系属性的索引-

INDEX ON :Amount(AMNT), and a Constraints on node property-CONSTRAINT ON (customer:Customet) ASSERT customer.ACCT IS UNIQUE

我的查询是:

 CALL apoc.export.csv.query("MATCH (x:Customer) with x CALL
 apoc.cypher.run(\"CALL apoc.path.expandConfig(x,
 {relationshipFilter:'Amount>', labelFilter:'+Customer', uniqueness:
 'NODE_PATH' } ) YIELD path return path as path\", {x:x}) YIELD value
 unwind nodes(value.path) as nodes unwind relationships(value.path) as
 rels  with collect(distinct nodes) as nodelist, collect(distinct rels)
 as rellist,x.ACCT as CustNumber with size(nodelist) as numOfMember,
 reduce(s = 0, r IN rellist | s + TOINT(r.AMNT)) AS totalAMNT
 ,CustNumber where (numOfMember > 100) and  ( totalAMNT > 100000) return
 CustNumber,numOfMember,totalAMNT ","results.csv",{});

但是查询运行很慢,很长一段时间后我得到这个错误:

解组返回标头时出错;嵌套异常 是:java.net.SocketException:软件导致连接中止:recv 失败

请帮帮我。

【问题讨论】:

    标签: neo4j


    【解决方案1】:

    我感觉您的两个背靠背 UNWINDS 正在创建大量结果记录(路径中每个节点与路径中每个关系的交叉乘积,对于从所有扩展而来的每个可能路径:客户节点)。不要这样做,你可能会炸毁你的堆。

    另外,我强烈建议您在单个 :Customer 节点上对内部查询进行 PROFILE,看看发生了什么,尤其是查询中的行数如何增加。

    我在摸不着头脑,为什么你在这里使用apoc.cypher.run() 来结束对apoc.path.expandConfig() 的调用。除非有充分的理由,否则我建议完全删除 apoc.cypher.run() 的使用。

    我们还可以使用一些 UNWINDing 的替代方法,使用一些 APOC 过程来展平和获取集合中的不同值,并提前过滤一些结果以避免处理只会在以后过滤掉的记录。

    不妨试试这样的:

    CALL apoc.export.csv.query("
    MATCH (x:Customer) 
    CALL apoc.path.expandConfig(x, {relationshipFilter:'Amount>', labelFilter:'+Customer', uniqueness: 'NODE_PATH' } ) YIELD path
    WITH x, collect(nodes(path)) as allPathNodes, collect(relationships(path)) as allPathRels
    WITH x, size(apoc.coll.toSet(apoc.coll.flatten(allPathNodes))) as numOfMember, allPathRels
    WHERE numOfMember > 100
    WITH x, numOfMember, apoc.coll.toSet(apoc.coll.flatten(allPathRels)) as rellist
    WITH x, numOfMember, apoc.coll.sum([r in rellist | TOINT(r.AMNT)]) as totalAMNT
    WHERE totalAMNT > 100000
    RETURN x.ACCT as CustNumber, numOfMember, totalAMNT ","results.csv",{});
    

    根据您的图表,expandConfig() 调用可能很昂贵。您可能想看看您是否可以在合理的时间内完成此调用并获得预期的路径数。试试这个:

    MATCH (x:Customer) 
    CALL apoc.path.expandConfig(x, {relationshipFilter:'Amount>', labelFilter:'+Customer', uniqueness: 'NODE_PATH' } ) YIELD path
    RETURN count(path) as paths
    

    如果您只想要到每个节点的单个路径而不是到每个节点的所有路径,则可以使用 apoc.path.spanningTree()(或使用 NODE_GLOBAL 唯一性,这将是等效的)获得更有效的查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多