2014-10-10 77 views
0

我有一個看起來像這樣一個複雜的分層查詢:Neo4j的複雜hieharchical的Cypher查詢性能下降

MATCH (comp:Company {id: 7})-[:HAS_SPACE]->(s:Space)-[:HAS_BOARD]->(b), 
(col)<-[:HAS_COLUMN]-(b)-[:HAS_LANE]->(lane) 
OPTIONAL MATCH (b)-[:HAS_CARD]->(card {archived: false}), 
(cardCol:Column)-[:HAS_CARD]->(card {archived: false})<-[:HAS_CARD]-(cardLane:Lane) 
WITH s, b, col, lane, { id: card.id, title: card.title, sort_order: card.sort_order, column_id: cardCol.id, lane_id: cardLane.id } as crd 
WITH s, { id: b.id, title: b.title, left: b.left, top: b.top, 
columns: collect(distinct {id: col.id, title: col.title, col_count: col.col_count, sort_order: col.sort_order}), 
lanes: collect(distinct {id: lane.id, title: lane.title, row_count: lane.row_count, sort_order: lane.sort_order}), 
cards: collect(distinct crd)} as brd 
RETURN {id: s.id, title: s.title, boards: collect(distinct brd)} 

這個查詢減慢到10秒時的卡的數量約爲200什麼是它的問題,我怎樣才能描述它?看起來好像有一個PROFILE關鍵字,但輸出結果看起來並不像真正的信息。順便說一下,我們在heroku上使用GrapheneDB。

+2

你有到位的任何索引查詢嘗試新的查詢規劃?看起來你應該索引'存檔'和'ID'。您可能會考慮爲其中一些比賽添加標籤 - 這可能有助於提高速度。 – FrobberOfBits 2014-10-10 14:13:26

+0

Thanx。是的,我有一個id的索引。此外,只有一家公司,所以在這種情況下,索引並不重要。至於存檔,只有兩個選項:true和false將索引幫助在這種情況下? 「你可能會考慮在其中一些比賽中添加標籤」 - 你是什麼意思? – Voice 2014-10-10 15:36:40

+0

通過添加標籤,我的意思是你的查詢有一個節點(b)沒有標籤;取決於圖的結構,指出匹配的標籤可以通過讓db考慮更少的候選節點來加速匹配。但你在這裏花費的大部分時間可能在收集(distinct())位 – FrobberOfBits 2014-10-10 15:44:42

回答

0

經過一番研究發現,如果我們將節點「非規範化」一點點添加lane_id和column_id到卡上,這個查詢運行得更快20倍。它仍然不是最快的解決方案,我不喜歡這種消除關係的非規範化。所以,我會很感激任何其他解決方案

1

我認爲你有這個查詢的一個問題是路徑上的組合爆炸,你可以幫助密碼(有關它的下一個版本會更聰明)。

此外,您的「可選關係」在哪裏?板和卡之間?

create index on :Company(id); 

MATCH (comp:Company {id: 7})-[:HAS_SPACE]->(s:Space)-[:HAS_BOARD]->(b) 
WITH distinct s, b 
MATCH (col)<-[:HAS_COLUMN]-(b)-[:HAS_LANE]->(lane) 
OPTIONAL MATCH (b)-[:HAS_CARD]->(card {archived: false}) 
WITH distinct s, b, col, lane, b, card 
MATCH (cardCol:Column)-[:HAS_CARD]->(card {archived: false})<-[:HAS_CARD]-(cardLane:Lane) 

WITH s, b, col, lane, 
    { id: card.id, title: card.title, sort_order: card.sort_order, 
    column_id: cardCol.id, lane_id: cardLane.id } as crd 

WITH s, 
    { id: b.id, title: b.title, left: b.left, top: b.top, 
    columns: collect(distinct {id: col.id, title: col.title, 
           col_count: col.col_count, sort_order: col.sort_order}), 
    lanes: collect(distinct {id: lane.id, title: lane.title, row_count: lane.row_count, 
           sort_order: lane.sort_order}), 
    cards: collect(distinct crd)} as brd 

RETURN {id: s.id, title: s.title, boards: collect(distinct brd)} 

這有助於單獨分析查詢的不同部分,看看那裏的組合爆炸踢,然後修復一塊回來了不同的基數。

您也可以通過在前面用cypher 2.1.experimental

+0

謝謝Michael,你的版本比初始查詢快10倍。只是好奇有沒有什麼好的指導如何寫一個複雜的查詢,並避免這種pifalls?此外,我還嘗試了網絡客戶端2.1.experimental - 沒有顯示任何有價值的信息,或者我錯過了一些東西。 – Voice 2014-10-11 13:24:22

+0

該查詢比初始查詢更快,但仍會隨着數據量的增加而降低。我猜組合爆炸會在這裏上升:(cardCol:Column) - [:HAS_CARD] - >(card {archived:false})< - [:HAS_CARD] - (cardLane:Lane),但真的不知道原因這個。所以任何想法如何避免這一點表示讚賞 – Voice 2014-10-22 06:47:20