Neo4j的复杂hieharchical的Cypher查询性能下降
问题描述:
我有一个看起来像这样一个复杂的分层查询: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。
答
经过一番研究发现,如果我们将节点“非规范化”一点点添加lane_id和column_id到卡上,这个查询运行得更快20倍。它仍然不是最快的解决方案,我不喜欢这种消除关系的非规范化。所以,我会很感激任何其他解决方案
答
我认为你有这个查询的一个问题是路径上的组合爆炸,你可以帮助密码(有关它的下一个版本会更聪明)。
此外,您的“可选关系”在哪里?板和卡之间?
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
你有到位的任何索引查询尝试新的查询规划?看起来你应该索引'存档'和'ID'。您可能会考虑为其中一些比赛添加标签 - 这可能有助于提高速度。 – FrobberOfBits 2014-10-10 14:13:26
Thanx。是的,我有一个id的索引。此外,只有一家公司,所以在这种情况下,索引并不重要。至于存档,只有两个选项:true和false将索引帮助在这种情况下? “你可能会考虑在其中一些比赛中添加标签” - 你是什么意思? – Voice 2014-10-10 15:36:40
通过添加标签,我的意思是你的查询有一个节点(b)没有标签;取决于图的结构,指出匹配的标签可以通过让db考虑更少的候选节点来加速匹配。但你在这里花费的大部分时间可能在收集(distinct())位 – FrobberOfBits 2014-10-10 15:44:42