我有一个带有搜索的多个实体的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
查询分析如下:
答案 0 :(得分:1)
因此,您当前的计划有3个并行线程。我们现在可以忽略它,因为它的命中率为0db。
您获得的最大成功是(mt:MemberTopics) ... WHERE mt.member_id = id
的比赛。我猜测member_id是唯一的ID,因此您将要在CREATE INDEX ON :MemberTopics(member_id)
上创建索引。这将使Cypher可以执行索引查找,而不是进行节点扫描,这将使数据库命中率从〜30mill减少到〜1(而且,在某些情况下,内联属性匹配对于更复杂的查询而言更快。因此{{1 }}更好。它明确表明此条件在匹配时必须始终为true,并将加强使用索引查找的作用)
第二大命中是点距离检查。目前,这是独立完成的,因为节点扫描需要很长时间。在对MemberTopic进行更改后,计划者应该切换到查找所有已连接的场所,然后仅对thous进行距离检查,这样也应该更便宜。
此外,看来mt和gt是由主题链接的,并且您正在使用主题ID对其进行对齐。如果假设t和t1是相同的Topic节点,则可以对两个节点都使用t来强制执行t,然后不需要进行id检查即可链接mt和gt。如果t和t1不是同一节点,则在节点属性中使用前键表示您应该在两个节点之间具有关系,并且仅沿该边缘移动(关系也可以具有属性,但是上下文看起来很像t和t1假定是同一个节点。您也可以说(mt:MemberTopics {member_id:id})
来强制执行此操作,但此时,您应该只对两个节点都使用t)
最后,根据查询返回的行数,您可能需要使用LIMIT和SKIP来分页结果。这看起来像信息传递给用户,我怀疑他们是否需要完整的转储。因此,仅返回最上面的结果,仅在用户希望查看更多结果时处理其余结果。 (有用的结果接近一公吨)由于到目前为止您只有21个结果,所以这现在就不成问题了,但是请记住,因为您需要扩展到100,000+个结果。