使用Neo4j .Net客户端时边缘创建速度太慢

问题描述:

我已经有大约800k个节点,并且我尝试使用Neo4j .Net客户端将约800万条边缘插入到Neo4j企业版中。使用Neo4j .Net客户端时边缘创建速度太慢

我正在做这样的事情,这个过程真的很慢。尝试过Neo4j的驱动程序,但速度也很慢。我也得到了名称字段索引。 任何人都可以请建议一种替代方法来更快地创建边缘?

public static async Task AddEdges(List<Edge> edgeTable, IGraphClient client) 
{ 

     try 
     { 
      foreach (var item in edgeTable) 
      { 
       await client.Cypher 
       .Match("(parentNode:MyNodeType)", "(childNode:MyNodeType)") 
       .Where((MyNodeType parentNode, MyNodeType childNode) => parentNode.Name == item.SourceName && childNode.Name==item.MemberName) 
       .Create("(childNode)-[:belongsTo]->(parentNode)") 
       .ExecuteWithoutResultsAsync(); 
      } 

     } 
     catch (Exception ex) 
     { 
      //ex handling 
     } 


} 
+0

需要多长时间? (如果没有实际的时间,你有估计吗?) –

您正在使用await把每个异步请求(由于您使用的ExecuteWithoutResultsAsync)进入同步请求。这意味着当前的http请求必须在发送下一个请求之前作出响应,即使您不关心响应。 (顺便说一下,为了达到同样的目的,你可以使用ExecuteWithoutResults而不使用await。)这种串行化应尽可能避免。但是,根据您的使用情况,并行执行时存在死锁的可能性(由于在创建新关系时写入端节点锁定)。

此外,您只在每个事务性请求中执行单个CREATE操作。这意味着您正在制作800万个序列化的事务请求。自然,这会很慢。

一个允许一定程度的异步操作,同时避免死锁的解决方案将涉及分析数据(理想情况下,以编程方式)以创建与其他组没有重叠节点的边组。即使组内的边缘仍然需要同步处理,不同的组可以并行处理而不会发生死锁。

如果您可以在单个事务中对一个组内的N个边执行操作,那么您可以避免为该组创建N个同步事务请求的开销,并且也可以避免上述死锁。

使用UNWIND子句,您可以对单个请求中的列表中的数据进行迭代操作。像下面的东西应该工作。注意,edgeTable输入列表必须从一个单一的组包含的边缘上,如以上所讨论:

public static async Task AddEdges(List<Edge> edgeTable, IGraphClient client) { 
    try { 
     client.Cypher 
      .Unwind(edgeTable, "item") 
      .Match("(parentNode:MyNodeType)", "(childNode:MyNodeType)") 
      .Where((MyNodeType parentNode, MyNodeType childNode) => parentNode.Name == item.SourceName && childNode.Name==item.MemberName) 
      .Create("(childNode)-[:belongsTo]->(parentNode)") 
      .ExecuteWithoutResultsAsync(); 
    } catch (Exception ex) { 
     //ex handling 
    } 
} 

注意,我使用ExecuteWithoutResultsAsync而不01​​,使得基团异步处理。

但有一点需要注意的是,你不想让neo4j服务器一次处理太多,以免内存耗尽。因此,如果任何组太大,或者同时处理了太多的组,则可能需要限制调用AddEdges的速率,和/或将大组分成更小的块,并确保这些块同时相对于彼此进行处理。