Neo4j cyper性能简单匹配

时间:2015-09-01 09:44:35

标签: neo4j cypher

我有一个非常简单的密码,这让我表现不佳。 我有约。 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和电子邮件的索引,但我仍然不认为这种性能是可以接受的。任何想法我怎样才能改善这个?

2 个答案:

答案 0 :(得分:1)

首先,您可以profile查询,查找幕后发生的事情。

目前看起来该查询扫描数据库中的所有节点以完成查询。

原因:

  • Neo4j仅支持' ='操作(或' IN')
  • 要完成查询,它会逐个遍历所有节点,检查每个节点是否有有效的时间戳

没有直接的方法来处理这个问题。 您应该考虑创建正确的图形结构,以更有效地处理特定于时间的查询。如何在图数据库中表示时间有几种方法。

您可以查看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。

但我真的不建议沿着这条路走下去。