【发布时间】:2018-07-20 12:02:21
【问题描述】:
我有一个包含多个实体的 Neo4j 查询,我想使用节点对象批量传递参数。但是,我的查询执行速度不是很高。如何优化此查询并使其性能更好?
WITH $nodes as nodes
UNWIND nodes AS node
with node.id AS id, node.lon AS lon, node.lat AS lat
MATCH
(m:Member)-[mtg_r:MT_TO_MEMBER]->(mt:MemberTopics)-[mtt_r:MT_TO_TOPIC]->(t:Topic),
(t1:Topic)-[tt_r:GT_TO_TOPIC]->(gt:GroupTopics)-[tg_r:GT_TO_GROUP]->(g:Group)-[h_r:HAS]->
(e:Event)-[a_r:AT]->(v:Venue)
WHERE mt.topic_id = gt.topic_id AND
distance(point({ longitude: lon, latitude: lat}),point({ longitude: v.lon, latitude: v.lat })) < 4000 AND
mt.member_id = id
RETURN
distinct id as member_id,
lat as member_lat,
lon as member_lon,
g.group_name as group_name,
e.event_name as event_name,
v.venue_name as venue_name,
v.lat as venue_lat,
v.lon as venue_lon,
distance(point({ longitude: lon,
latitude: lat}),point({ longitude: v.lon, latitude: v.lat })) as distance
查询分析如下所示:
【问题讨论】:
-
你的索引是什么?一个直接的建议是索引
mt.member_id,然后先进行匹配,然后将其放入 with 子句中,然后匹配其余部分。这将减少相当多的工作量。 3000 万的“NodeByLabelScan”可能是最痛苦的。另外,为什么要将一个节点中的 ID 与另一个节点中的 ID 匹配?为什么这些节点之间没有关系?如果您可以创建它们,它也会变得更快。 -
t 和 t1 假设是同一个主题节点吗?如果是这样,你为什么要在那里分割查询?同时在
(mt:MemberTopics) mt.id上放置一个索引并内联规划器(mt:MemberTopics {id:id})的id 匹配,将把该部分从30mill db hits 减少到~1db hits。另外,您能否将其他框也展开,以便我们可以看到它们在做什么? -
匹配 MemberTopics 之后,距离搜索可能是下一个最昂贵的部分,但是一旦规划器可以在 1db 命中获得 MemberTopic,距离查找应该会快得多(因为它不会尝试并行执行,但仅在 mt 实际连接的节点上)
-
@Tezra 谢谢!创建索引和匹配 id 确实有助于提高性能!您可以将其发布为答案吗?
-
@Tezra 另外,我删除了查询中的拆分,它开始工作得更快。我首先使用了拆分,因为没有它,查询不会返回任何结果
标签: neo4j cypher graph-databases neo4j-apoc