Neo4j查询耗时长

mgdq6dx1  于 2023-10-18  发布在  其他
关注(0)|答案(1)|浏览(158)

我目前正在一个社会媒体网站,这完全是在用户的时间轴方面相同的工作,像用户可以遵循,创建,分享的职位,块,解除封锁,等.因此,我们创建了两种类型的标签“User”和“Post”,并有几个关系,如follow,block,private等。目前,我们有大约41000个节点和650000个关系。
硬件配置:8 GB RAM 2核心50 GB硬盘
1个Master和2个Slave
并使用以下查询获取用户的时间轴

MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'}),(p:Post{is_deleted:'0'}),(po:User{user_id:p.owner_id})
                  WHERE (p.post_type = '1' OR p.post_type = '4')  WITH n,p,po 
                WHERE po.is_active='1' AND  (n)-[:CREATED{own_status:'1'}]->(p) OR
                (n)-[:FOLLOWS{follow_status:'1'}]->(:User{is_active:'1'})-[:CREATED{own_status:'1'}]->(p)
                OR (n)-[:FOLLOWS{follow_status:'1'}]->(:Keyword{is_deleted:'0'})-[:KEYWORD]->(p)
                WITH n,p,po
                OPTIONAL MATCH (n)-[fr:FOLLOWS]->(po)
                WHERE fr.follow_status='1' WITH p,n,po,fr
                WHERE NOT ((n)-[:FOLLOWS{is_blocked:true}]->(po) OR (n)-[:FOLLOWS{is_mute:true}]->(po)) WITH p,n,po,fr
                WHERE NOT (n)<-[:FOLLOWS{is_blocked:true}]-(po) WITH p,n,po,fr
                WHERE (fr is not null and toInteger(po.is_private) <= 1 AND po.user_id <> n.user_id)
                OR (toInteger(po.is_private) <= 1 AND po.user_id = n.user_id)
                OR (toInteger(po.is_private) = 0 AND  po.user_id <> n.user_id) WITH p,n,po
                RETURN p,po,SIZE(()-[:LIKED]->(p)) as likecount,
                        SIZE((n)-[:LIKED]->(p)) as likestatus,count(*) as postcount
                ORDER BY p.created_at DESC
                SKIP 0 LIMIT 10

此查询耗时超过10秒。太高
下面是上述查询的配置文件

下面是索引列表

有谁能告诉我哪里做错了吗?

c9x0cxw0

c9x0cxw01#

如果你试图获取用户的时间轴,我认为你应该从特定的用户开始,然后通过你感兴趣的关系连接到其他节点。当前的查询没有利用模式匹配或图数据库的连接特性。
当前编写的查询的第一个match语句查找特定的用户,然后是具有属性is_deleted:'0'的所有Post节点,然后是连接到任何Post节点的所有User节点。这样搜索会在第一个中间的Expand(All)中得到比数据库中的节点数(41,000)更多的数据库命中数(54,984)。
在优化这个查询时,你应该得到最大的提升,那就是将搜索集中在单个用户上,然后使用关系从那里扩展:

MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'})-[r]-(p:Post{is_deleted:'0'})

这将匹配用户和通过关系连接到该用户的所有合格职位。请注意,如果用户没有连接到任何符合条件的职位,即使该用户确实存在于数据库中,也不会有任何匹配。
如果你只想包含某些关系类型,你可以在第一个MATCH语句中这样指定:

MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'})-[r:CREATED|FOLLOWS|KEYWORD]-(p:Post{is_deleted:'0'})

或者你可以像这样把它放在WHERE子句中:

MATCH (n:User {user_id:'12129bca-9b90-44c9-aae8-d80e61f9c342',is_active:'1'})-[r]-(p:Post{is_deleted:'0'})
WHERE type(r) in ['CREATED', 'FOLLOWS' , 'KEYWORD']

我没有遵循你所有的条件语句(我认为一旦你将其转换为模式匹配,你可能可以删除其中一些),但是一旦你有了你的初始模式,你可以添加任何你需要的条件语句。范例:

WHERE (p.post_type = '1' OR p.post_type = '4')
  AND (r.own_status = '1' OR r.follow_status = '1')
  AND NOT r.is_blocked = true

有关模式匹配的更多信息,请查看Neo4j Cypher Manual的第2.9节。

相关问题