2014-10-10 60 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