我有一个非常简单的密码,这让我表现不佳。 我有约。 200万用户和60个图书类别,从用户到类别的关系约为2800万。 当我做这个密码时:
MATCH (u:User)-[read:READ]->(bc:BookCategory)
WHERE read.timestamp >= timestamp() - (1000*60*60*24*30)
RETURN distinct(bc.id);
它在2 - 2.5(第一次)分钟内返回8.5k行
当我做这个密码时:
MATCH (u:User)-[read:READ]->(bc:BookCategory)
WHERE read.timestamp >= timestamp() - (1000*60*60*24*30)
RETURN u.id, u.email, read.timestamp;
在3到6(第一次)分钟内返回55k行。
我已经有用户ID和电子邮件的索引,但我仍然不认为这种性能是可以接受的。任何想法我怎样才能改善这个?
答案 0 :(得分:1)
首先,您可以profile查询,查找幕后发生的事情。
目前看起来该查询扫描数据库中的所有节点以完成查询。
原因:
没有直接的方法来处理这个问题。 您应该考虑创建正确的图形结构,以更有效地处理特定于时间的查询。如何在图数据库中表示时间有几种方法。
您可以查看graphaware/neo4j-timetree库。
答案 1 :(得分:0)
你能解释一下你的模特吗?
书籍和“阅读”在哪里?事件在哪里?
Afaik你想知道的,最近读过哪些书类(上个月)?
您可以创建第二种类型的关系,RECENTLY_READ
由超过30天的批处理作业到期(删除)。 (这可以是两个简单的cypher语句,用于创建和删除这些关系)。
WITH (1000*60*60*24*30) as month
MATCH (a:User)-[read:READ]->(b:BookCategory)
WHERE read.timestamp >= timestamp() - month
MERGE (a)-[rr:RECENTLY_READ]->(b)
WHERE coalesce(rr.timestamp,0) < read.timestamp
SET rr.timestamp = read.timestamp;
WITH (1000*60*60*24*30) as month
MATCH (a:User)-[rr:RECENTLY_READ]->(b:BookCategory)
WHERE rr.timestamp < timestamp() - month
DELETE rr;
还有另一种方法可以实现完全想要在这里做什么,但遗憾的是在Cypher中无法实现。
在您的阅读关系上使用timestamp
上的关系索引,您可以在Neo4j的Java API中运行Lucene-NumericRangeQuery。
但我真的不建议沿着这条路走下去。