代码之家  ›  专栏  ›  技术社区  ›  Cassie

提高NEO4J查询性能

  •  0
  • Cassie  · 技术社区  · 6 年前

    我有一个搜索了多个实体的NEO4J查询,我想使用nodes对象批量传递参数。但是,我的查询执行速度不是很快。如何优化此查询并提高其性能?

    以$nodes作为节点的 将节点作为节点展开 node.id为id,node.lon为lon,node.lat为lat 比赛 (m:member)-[mtg_r:m t_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:活动)-[a_r:地点]->(v:地点) 其中mt.topic_id=gt.topic_id和 距离(点(经度:lon,纬度:lat),点(经度:v.lon,纬度:v.lat))<4000和 mt.member_id=id 返回 将distinct id作为成员\u id, lat作为成员 朗作为会员, g.组名作为组名, e.事件名称作为事件名称, 五、场地名称为场地名称, V.lat作为场地 V.lon作为场地 距离(点(经度:lon, 纬度:lat),点(经度:v.lon,纬度:v.lat)作为距离

    查询分析如下所示:

    .

    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
    

    查询分析如下:

    1 回复  |  直到 6 年前
        1
  •  1
  •   Tezra    6 年前

    所以,您当前的计划有3个并行线程。一个我们现在可以忽略的,因为它有0db点击量。

    你要做的最大的打击就是比赛 (mt:MemberTopics) ... WHERE mt.member_id = id . 我猜会员号是唯一的ID,所以你要在上面创建一个索引 CREATE INDEX ON :MemberTopics(member_id) . 这将允许Cypher执行索引查找,而不是节点扫描,这将使数据库命中从~30英里减少到~1(在某些情况下,对于更复杂的查询,内联属性匹配更快)。所以 (mt:MemberTopics {member_id:id}) 更好。它明确表明,匹配时此条件必须始终为真,并且将加强使用索引查找)

    第二大打击是点距离检查。现在,这是独立完成的,因为节点扫描需要很长时间。一旦你对会员主题做了修改,规划者应该切换到查找所有连接的场馆,然后只进行千分之一的距离检查,这样也会变得更便宜。

    而且,看起来mt和gt是由主题链接的,您使用主题ID来对齐它们。如果T和T1被假定为同一个主题节点,那么您可以对这两个节点使用T来强制执行,然后就不需要执行ID检查来链接mt和gt。如果t和t1不是同一个节点,那么在节点的属性中使用foreign键表示应该在两个节点之间有一个关系,并且只沿着该边缘移动(关系也可以有属性,但是上下文看起来很像t和t1被假定为同一个节点)。你也可以通过说 WHERE t = t1 ,但在这一点上,您应该只对两个节点使用t)

    最后,根据查询返回的行数,您可能需要使用limit和skip来分页结果。这看起来像是给用户的信息,我怀疑他们需要完整的转储文件。因此,只返回最重要的结果,并且仅在用户希望看到更多结果时处理其余的结果。(当结果接近公制吨时很有用)因为到目前为止您只有21个结果,所以现在这不是一个问题,但请记住,您需要扩展到100000+个结果。