2013-05-07 26 views
1

這個問題類似於這兩個:16283441,15456345直接鄰居關係密碼查詢性能

UPDATE:這裏是database dump

在190K節點和727K的關係(和數據庫磁盤使用128MB)的數據庫,我想運行下面的query

START start_node=node(<id>) 
MATCH (start_node)-[r:COOCCURS_WITH]-(partner), 
     (partner)-[s:COOCCURS_WITH]-(another_partner)-[:COOCCURS_WITH]-(start_node) 
RETURN COUNT(DISTINCT s) as num_partner_partner_links; 

在這種DB 90%的節點有0的關係,其餘的10%從1到670,所以這個查詢返回的最大網絡不可能超過220K鏈接(670 * 670)/ 2)。

在小於10K partner_partner_links的節點上,查詢需要2-4秒。 對於更多的連接節點(20-45K鏈接),大約需要40-50秒(不知道多少連接節點最多)。

指定關係的方向有點幫助但不是很多(但是然後查詢不會返回我需要的返回)。

剖析上最大的節點之一查詢說:

==> ColumnFilter(symKeys=[" INTERNAL_AGGREGATE48d9beec-0006-4dae-937b-9875f0370ea6"], returnItemNames=["num_partner_links"], _rows=1, _db_hits=0) 
==> EagerAggregation(keys=[], aggregates=["( INTERNAL_AGGREGATE48d9beec-0006-4dae-937b-9875f0370ea6,Distinct)"], _rows=1, _db_hits=0) 
==> PatternMatch(g="(partner)-['r']-(start_node)", _rows=97746, _db_hits=34370048) 
==>  TraversalMatcher(trail="(start_node)-[ UNNAMED3:COOCCURS_WITH WHERE true AND true]-(another_partner)-[s:COOCCURS_WITH WHERE true AND true]-(partner)", _rows=116341, _db_hits=117176) 
==>  ParameterPipe(_rows=1, _db_hits=0) 
neo4j-sh (0)$ 

我不明白爲什麼會這樣如此緩慢,大部分的東西應該是在RAM反正。有可能在100毫秒以內,或者neo4j沒有達到那個標準嗎?我可以把了整個數據庫的地方,如果這將有助於..

最大的難題是相同的查詢改寫爲不同節點的符號:)

START n=node(36) 
MATCH (n)-[r:COOCCURS_WITH]-(m), 
     (m)-[s:COOCCURS_WITH]-(p)-[:COOCCURS_WITH]-(n) 
RETURN COUNT(DISTINCT s) AS num_partner_partner_links; 

START start_node=node(36) 
MATCH (start_node)-[r:COOCCURS_WITH]-(partner), 
     (partner)-[s:COOCCURS_WITH]-(another_partner)-[:COOCCURS_WITH]-(start_node) 
RETURN COUNT(DISTINCT s) AS num_partner_partner_links; 

前者總是在運行時所使用的運行速度較慢+4.2秒,後者在3.8以下,無論我運行多少次(交錯)!?

SW/HW細節:(高級)的Neo4j v1.9.RC2,JDK 1.7.0.10,一個的MacBook Pro與SSD磁盤,8GBRAM,2核i7,具有以下的Neo4j配置:

neostore.nodestore.db.mapped_memory=550M 
neostore.relationshipstore.db.mapped_memory=540M 
neostore.propertystore.db.mapped_memory=690M 
neostore.propertystore.db.strings.mapped_memory=430M 
neostore.propertystore.db.arrays.mapped_memory=230M 
neostore.propertystore.db.index.keys.mapped_memory=150M 
neostore.propertystore.db.index.mapped_memory=140M 

wrapper.java.initmemory=4092 
wrapper.java.maxmemory=4092 

回答

0

將您的查詢更改爲下面的查詢。在我的筆記本電腦上,比你的規格低得多,執行時間減半。

START start_node=node(36) 
MATCH (start_node)-[r:COOCCURS_WITH]-(partner) 
WITH start_node, partner 
MATCH (partner)-[s:COOCCURS_WITH]-(another_partner)-[:COOCCURS_WITH]-(start_node) 
RETURN COUNT(DISTINCT s) AS num_partner_partner_links; 

此外,與默認設置相比,使用您的設置不會影響性能。恐怕你無法得到你想要的表演,但這個問題是朝正確方向邁出的一步。

通常遍歷API將比Cypher更快,因爲您明確地控制遍歷。我模仿查詢,如下所示:

public class NeoTraversal { 

public static void main(final String[] args) { 
    final GraphDatabaseService db = new GraphDatabaseFactory() 
      .newEmbeddedDatabaseBuilder("/neo4j") 
      .loadPropertiesFromURL(NeoTraversal.class.getClassLoader().getResource("neo4j.properties")) 
      .newGraphDatabase(); 
    final Set<Long> uniquePartnerRels = new HashSet<Long>(); 
    long startTime = System.currentTimeMillis(); 
    final Node start = db.getNodeById(36); 
    for (final Path path : Traversal.description() 
      .breadthFirst() 
      .relationships(Rel.COOCCURS_WITH, Direction.BOTH) 
      .uniqueness(Uniqueness.NODE_GLOBAL) 
      .evaluator(Evaluators.atDepth(1)) 
      .traverse(start)) { 
     Node partner = start.equals(path.startNode()) ? path.endNode() : path.startNode(); 
     for (final Path partnerPath : Traversal.description() 
       .depthFirst() 
       .relationships(Rel.COOCCURS_WITH, Direction.BOTH) 
       .uniqueness(Uniqueness.RELATIONSHIP_PATH) 
       .evaluator(Evaluators.atDepth(2)) 
       .evaluator(Evaluators.includeWhereEndNodeIs(start)) 
       .traverse(partner)) { 
      uniquePartnerRels.add(partnerPath.relationships().iterator().next().getId()); 
     } 
    } 
    System.out.println("Execution time: " + (System.currentTimeMillis() - startTime)); 
    System.out.println(uniquePartnerRels.size()); 
} 

static enum Rel implements RelationshipType { 
    COOCCURS_WITH 
} 

} 

這顯然優於CYPHER查詢,因此這可能是你一個不錯的選擇。優化可能仍然有可能。

+0

你說得對兩個,你的暗號查詢是稍快,並遍歷查詢至少快兩倍!但它仍然不是我需要的地方:/ 10K結果需要1秒,對於最大節點需要20秒.. ps。在遍歷查詢中有2個錯誤,希望我可以編輯你的答案。 – milan 2013-05-14 13:09:02

+0

您可以通過在集合中添加關係標識符來獲得一點速度。我再次編輯了代碼。你會再次獲得一些時間,但它當然不會創造奇蹟。 – tstorms 2013-05-14 13:20:35

+0

最大的瓶頸是你需要在兩個方向上進行遍歷。無法將您的數據建模爲僅指向一個方向? – tstorms 2013-05-14 13:23:10

0

似乎只是深度/寬度的第一遍遍,neo4j不是那麼「快速」。我已經通過預先計算所有網絡並將它們存儲到MongoDB中解決了這個問題。描述一個網絡中的節點文件看起來是這樣的:

{ 
    node_id : long, 
    partners : long[], 
    partner_partner_links : long[] 
} 

Partners和partner_partner_links是描述egdes文件的ID。獲取整個網絡需要2個疑問:一個用於這個文件,另一個是邊緣性(亦持有節點屬性):

db.edge.find({"_id" : {"$in" : network.partner_partner_links}});