2015-04-06 87 views
5

我們有一個Neo4J數據庫,代表一個具有大約100K節點和200K關係的演化過程。節點代代相傳,邊代表親子關係。主要目標是能夠在最後一代中獲得一個或多個感興趣的節點,並探索它們的進化歷史(粗略地說,「我們是如何到達這裏的?」)。尋求Neo4J Cypher查詢很長(但幾乎)唯一的路徑

的「明顯的」第一次查詢找到自己的所有祖先不工作,因爲有通過空間太多的可能祖先和路徑:

match (a)-[:PARENT_OF*]->(c {is_interesting: true}) 
return distinct a; 

因此,我們已經預先處理過的數據,以便某些邊被標記爲「特殊」,使得每個節點至多具有一個「特殊」父邊,儘管偶爾兩個父邊都被標記爲「特殊」。我希望,那麼,是這條查詢(有效)生成一起「特殊」的邊緣(幾乎)獨特的道路:

match (a)-[r:PARENT_OF* {special: true}]->(c {is_interesting: true}) 
return distinct a; 

然而,這仍然是unworkably緩慢。

這很令人沮喪,因爲「作爲一個人」,其邏輯很簡單:從少量的「有趣」節點開始(通常爲1,最多不超過幾十個),並沿着幾乎總是唯一的「特殊「的邊緣。假設具有兩個「特殊」父節點的節點數量非常少,這應該是類似於O(N)的東西,其中N是時間回退的代數。

在Neo4j的,但是,可以追溯到從那裏步驟是唯一一個獨特的「有趣」的節點25步,但需要30秒,而一旦有一個分叉(其中父母雙方均爲「特殊」 )作爲步驟的函數,它會變得更糟。 28步(使我們到達第一個分岔點)需要2分鐘,30分鐘(仍然只有一個分岔點)需要6分鐘,而我甚至沒有想過在模擬開始時嘗試完整的100步。

去年的一些類似工作似乎表現更好,但我們使用了各種邊緣標籤(例如,(a)-[:SPECIAL_PARENT_OF*]->(c)以及(a)-[:PARENT_OF*]->(c)),而不是在邊緣使用數據字段。查詢關係字段值不是一個好主意嗎?我們在這個模型(一些布爾值,一些數字)中關聯了不同的值,並且我們希望/假設我們可以使用這些值來有效地限制搜索,但也許情況並非如此。

有關如何調整我們的模型或查詢的建議將不勝感激。

更新我應該提到,這是所有與Neo4J 2.1.7。按照布萊恩安德伍德的建議,我會給2.2一個嘗試,並會報告回來。

+0

我真的很想親自看到這個答案。我肯定有一些開放式路徑長度的Cypher查詢,看起來他們不應該穿越很多,但需要一段時間。 – 2015-04-06 07:24:27

回答

2

在使用Neo4J 2.2中的剖析工具探索事物之後(感謝Brian Underwood提供的技巧),很明顯Neo4J不會對邊緣屬性進行任何預過濾,這會導致令人討厭的組合長路徑爆炸。

例如原始查詢:

match (a)-[r:PARENT_OF* {special: true}]->(c {is_interesting: true}) 
return distinct a; 

發現所有路徑從ac然後消除了具有邊緣不special的那些。由於有從ac的數百萬條路徑,這是完全不可行的。

如果我不是增加一個IS_SPECIAL邊緣的地方有一個PARENT_OF邊緣有{special: true},那麼查詢變得真快,讓我推回約100代在第二下。

此查詢創建的所有新邊:

match (a)-[r:PARENT_OF {special: true}]->(b) 
create (a)-[:IS_SPECIAL]->(b); 

和第二下帶給我們的圖形添加91K關係。

然後

match (c {is_interesting: true}) 
with c 
match (a)-[:IS_SPECIAL*]->(c) 
return distinct a; 

需要一秒鐘下沿「特殊」路徑找到節點112從一個唯一的目標節點c回來。首先匹配c並且使用with c限制節點集合似乎也很重要,因爲Neo4J似乎也不對節點屬性進行預先過濾,並且如果有幾個「有趣的」目標節點,事情會變得很慢。

2

我已經有一些運氣,指定了路徑長度的限制。所以,如果你知道這是從來沒有超過30周跳,你可以嘗試:

MATCH (c {is_interesting: true}) 
WITH c 
MATCH (a)-[:PARENT_OF*1..30]->c 
RETURN DISTINCT a 

此外,有沒有對is_interesting性的指標?這肯定會導致緩慢。

您使用的是什麼版本的Neo4j?如果您正在使用或者如果您升級到2.2。0,你要使用新的查詢分析工具:

http://neo4j.com/docs/2.2.0/how-do-i-profile-a-query.html

此外,如果您在Web控制檯使用它們,你得到一個不錯的圖形上下的樹的事情(技術術語),顯示每一個步驟。

+0

我們絕對想要走很長的路。作爲一種解決方法,我們一直在做短路徑,但一個明確的目標是能夠一路推回到模擬的開始。 我認爲有'is_interesting'屬性的索引。運行'schema ls'至少會列出它。 我們正在使用2.1.7(抱歉沒有列出版本),但我肯定會嘗試2.2並查看是否有助於這種情況,或者如果分析工具可能有助於澄清正在發生的事情。 感謝您的建議。 – 2015-04-06 15:14:54

+0

切換到2.2並未提高性能,但分析工具的確有助於明確問題所在。它使用'is_interesting'屬性生成全部路徑_without_,然後_then_用'is_interesting'屬性進行過濾。最初的一組路徑很快就會變得非常龐大,因此這些查詢需要永久。我在猜測,如果我們有'IS_INTERESTING'作爲標籤的特殊優勢,那麼它就可以在預先過濾路徑列表中使用它,從而加快速度。 – 2015-04-06 15:40:01

+0

也許也可以先使用WITH子句進行過濾? – 2015-04-06 15:50:57