2017-05-04 78 views
0

我已經有大約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

需要多長時間? (如果沒有實際的時間,你有估計嗎?) –

回答

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的速率,和/或將大組分成更小的塊,並確保這些塊同時相對於彼此進行處理。