我创建了一个类似于某些客户端数据的测试数据集,其结构如下:
*1 100k *3..30
[:author]--------> person <---------[:member]
| | |
| *2..8 |
| [:topic] |
| | |
| *3..8 V *3..8 |
article-[:topic]-> topic <-[:topic]- project
1m 1k 20k
数字表示例如我有100万篇文章,每篇文章都有一位作者,每篇文章都有3到8篇文章,涉及1000个主题之一。
现在我有两个问题:
第一:这种布局是否有意义?主题变成超级节点 - 将它们作为节点上的属性会更好吗?
其次,我发现查询存在巨大的性能差异,具体取决于我的表达方式。我们的想法是找到一起参与项目的人,并分享个人对某个主题的兴趣:
QUERY1
match
n:person<-[:member]-p:project-[:member]->m,
n-[:topic]->t,
m-[:topic]->t
where
n.name='person1215' and
n<>m
return
m,t;
返回1500ms-9000ms
范围。
query2 要快得多:
match
n:person<-[:member]-p:project-[:member]->m,
n-[:topic]->t1,
m-[:topic]->t2
where
n.name='person1250' and
n<>m and
t1=t2
return
t1,m;
在200ms-400ms
中返回。
第二:为什么query2这么快? 如何通过查看该查询来看到这一点?
query1 的Profiler输出:
ColumnFilter(symKeys=["n", "t", "m", " UNNAMED14", "p", " UNNAMED51", " UNNAMED35", " UNNAMED66"], returnItemNames=["m", "t"], _rows=3, _db_hits=0)
Filter(pred="((NOT(n == m) AND hasLabel(p: project)) AND hasLabel(p: project))", _rows=3, _db_hits=0)
PatternMatch(g="(p)-[' UNNAMED35']-(m),(p)-[' UNNAMED14']-(n),(m)-[' UNNAMED66']-(t),(n)-[' UNNAMED51']-(t)", _rows=3, _db_hits=0)
SchemaIndex(identifier="n", _db_hits=0, _rows=1, label="person", query="Literal(person1215)", property="name")
和 query2 :
ColumnFilter(symKeys=["n", " UNNAMED67", "m", " UNNAMED14", "t2", "p", " UNNAMED51", "t1", " UNNAMED35"], returnItemNames=["t1", "m"], _rows=2, _db_hits=0)
Filter(pred="(((NOT(n == m) AND t1 == t2) AND hasLabel(p: project)) AND hasLabel(p: project))", _rows=2, _db_hits=0)
PatternMatch(g="(p)-[' UNNAMED35']-(m),(p)-[' UNNAMED14']-(n),(m)-[' UNNAMED67']-(t2),(n)-[' UNNAMED51']-(t1)", _rows=2, _db_hits=0)
SchemaIndex(identifier="n", _db_hits=0, _rows=1, label="person", query="Literal(person1250)", property="name")
非常感谢,
约尔格
答案 0 :(得分:1)
Joerg,可能是您在模式匹配器选择中发现了一个错误,这些查询实际上应该使用遍历匹配器。
如果您提出GitHub问题,我们会跟进那个问题。非常感谢!!
对于“超级节点” - 主题,使用较少的通用关系类型可能是有意义的,这些关系类型允许节点的子组织(在内存中)。例如。 :project_topic
,article_topic
,:interest_topic
。你可以尝试一下吗?
然后你的查询将是:
match
n:person<-[:member]-p:project-[:member]->m,
n-[:interest_topic]->t,
m-[:interest_topic]->t
where
n.name='person1215' and
n<>m
return
m,t;
顺便说一下。由于节点唯一性约束m
实际上应该与n不一样,你在查询中看到了吗?
如果您退出第二次标签检查(对于:project
,只是好奇)会发生什么事情也会很有趣。
另外,请注意2.0尚未进行性能优化。对于专门的人员查找,它将更快地接近GA。