密码性能的差异取决于措辞?

时间:2013-08-08 13:49:33

标签: performance neo4j cypher

我创建了一个类似于某些客户端数据的测试数据集,其结构如下:

   *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")

非常感谢,

约尔格

1 个答案:

答案 0 :(得分:1)

Joerg,可能是您在模式匹配器选择中发现了一个错误,这些查询实际上应该使用遍历匹配器。

如果您提出GitHub问题,我们会跟进那个问题。非常感谢!!

对于“超级节点” - 主题,使用较少的通用关系类型可能是有意义的,这些关系类型允许节点的子组织(在内存中)。例如。 :project_topicarticle_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。