Neo4j Cypher优化创建笛卡尔乘积中每个节点之间的关系

Neo4j Cypher优化创建笛卡尔乘积中每个节点之间的关系,neo4j,cypher,Neo4j,Cypher,我有一组节点,都标记为Word。我想用一种叫做距离的关系把每个单词和所有其他单词联系起来。我执行以下查询: match (word1:Word) with word1 match (word2:Word) where word1 <> word2 merge (word1)-[distance:DISTANCE ]->(word2) return word1, distance, word2 匹配(word1:Word) 用词1 匹配(word2:Word) 其中word1 word2 合

我有一组节点,都标记为Word。我想用一种叫做距离的关系把每个单词和所有其他单词联系起来。我执行以下查询:

match (word1:Word) with word1 match (word2:Word) where word1 <> word2 merge (word1)-[distance:DISTANCE ]->(word2) return word1, distance, word2 匹配(word1:Word) 用词1 匹配(word2:Word) 其中word1 word2 合并(word1)-[distance:distance]->(word2) 返回单词1、距离、单词2 它永远运行。只有约600个节点,尽管我预计有600*600个关系,但查询不应该运行两个小时!在Java中比在Neo4j中更快。你有什么建议可以让它更快?我已经在其中一个属性上添加了一个索引,但没有改进。

一些观察结果:

  • 您的查询将尝试在单个事务中执行2*600*599(或718800)
    MERGE
    操作。之所以使用
    2
    ,是因为每对单词(比如x和y)都会被看到两次(x/y和y/x)。您(大概)只想执行一半的操作
  • x/y和y/x行为还导致尝试确保每个词对有2个
    距离
    关系——两个方向各一个。这(大概)是你想要(或需要)的两倍
  • 尝试在单个事务中执行720K(甚至仅360K)操作可能会导致DB服务器内存不足
  • 下面是一个经过修改的查询,它可能会修复上述问题。
    ID(w1)
    测试确保一对中的两个字不相同,并且同一对只处理一次。它还使用APOC过程在单独的事务中并行地一次创建10K个关系

    CALL apoc.periodic.iterate(
      'MATCH (w1:Word), (w2:Word) WHERE ID(w1) < ID(w2) RETURN w1, w2',
      'CREATE (w1)-[:DISTANCE]->(w2)',
      {batchSize:10000, parallel:true}) YIELD batches, total
    RETURN *
    
    调用apoc.periodic.iterate(
    '匹配(w1:Word),(w2:Word),其中ID(w1)(w2)',
    {batchSize:10000,parallel:true})产量批次,总计
    返回*
    
    注1:此查询假设您开始时数据库中没有任何
    距离
    关系,因此它使用更便宜的
    CREATE
    子句而不是
    MERGE
    。如果距离关系已存在,则改用合并关系(但如果第一个关系位于相反方向,则可能会在同一对之间创建第二个关系)

    注2:并行执行批处理应该是安全的,因为新密码不可能出现问题2。如果两个事务试图同时在相同的两个节点之间以相反的方向创建关系,则可能会导致错误,这将导致至少一个事务失败

    注3:此查询假设第一条语句(带有
    MATCH
    子句)本身没有内存不足或处理时间过长。如果这个假设是错误的,那么使用经过适当修改的查询应该会起作用。

    一些观察结果:

  • 您的查询将尝试在单个事务中执行2*600*599(或718800)
    MERGE
    操作。之所以使用
    2
    ,是因为每对单词(比如x和y)都会被看到两次(x/y和y/x)。您(大概)只想执行一半的操作
  • x/y和y/x行为还导致尝试确保每个词对有2个
    距离
    关系——两个方向各一个。这(大概)是你想要(或需要)的两倍
  • 尝试在单个事务中执行720K(甚至仅360K)操作可能会导致DB服务器内存不足
  • 下面是一个经过修改的查询,它可能会修复上述问题。
    ID(w1)
    测试确保一对中的两个字不相同,并且同一对只处理一次。它还使用APOC过程在单独的事务中并行地一次创建10K个关系

    CALL apoc.periodic.iterate(
      'MATCH (w1:Word), (w2:Word) WHERE ID(w1) < ID(w2) RETURN w1, w2',
      'CREATE (w1)-[:DISTANCE]->(w2)',
      {batchSize:10000, parallel:true}) YIELD batches, total
    RETURN *
    
    调用apoc.periodic.iterate(
    '匹配(w1:Word),(w2:Word),其中ID(w1)(w2)',
    {batchSize:10000,parallel:true})产量批次,总计
    返回*
    
    注1:此查询假设您开始时数据库中没有任何
    距离
    关系,因此它使用更便宜的
    CREATE
    子句而不是
    MERGE
    。如果距离关系已存在,则改用合并关系(但如果第一个关系位于相反方向,则可能会在同一对之间创建第二个关系)

    注2:并行执行批处理应该是安全的,因为新密码不可能出现问题2。如果两个事务试图同时在相同的两个节点之间以相反的方向创建关系,则可能会导致错误,这将导致至少一个事务失败


    注3:此查询假设第一条语句(带有
    MATCH
    子句)本身没有内存不足或处理时间过长。如果这个假设是错误的,那么使用一个经过适当修改的查询应该会起作用。

    一个事务中几乎创建了360K个关系,这在很大程度上取决于您的内存设置。请注意,您还返回了360K行。至少,你可以消除你的回报,因为你似乎不需要它。如果不打算在查询中进一步使用:DISTANCE关系,也不需要在该关系上添加变量。如果需要对合并进行批处理,请尝试APOC库过程APOC.periodic.commit()。一个事务中几乎创建了360K个关系,这可能很大程度上取决于内存设置。请注意,您还返回了360K行。至少,你可以消除你的回报,因为你似乎不需要它。如果不打算在查询中进一步使用:DISTANCE关系,也不需要在该关系上添加变量。如果您需要批量合并,请尝试AP