【问题标题】:Neo4j Cypher query for similarity calculation slow performance用于相似度计算的 Neo4j Cypher 查询性能缓慢
【发布时间】:2014-05-15 20:07:35
【问题描述】:

我是 Neo4j/Graph 数据库的新手,我正在尝试复制 Cypher 食谱中的教程:http://docs.neo4j.org/chunked/stable/cypher-cookbook-similarity-calc.html

随机数据集包含 100 种食物和 1500 人,所有人都通过具有“倍”整数属性的 ATE 关系与食物相关。食物和人被标记并具有属性“名称” - 由自动索引索引

neo4j-sh (?)$ dbinfo -g "Primitive count"
{
  "NumberOfNodeIdsInUse": 1600,
  "NumberOfPropertyIdsInUse": 151600,
  "NumberOfRelationshipIdsInUse": 150000,
  "NumberOfRelationshipTypeIdsInUse": 1
}

neo4j-sh (?)$ index --indexes
Node indexes:
  node_auto_index
Relationship indexes:
  relationship_auto_index

在 neo4j-shell 中从说明书运行修改后的查询永远不会完成(可能是因为节点/关系太多?):

EXPORT name="Florida Goyette"
MATCH (me:Person { name: {name}})-[r1:ATE]->(food)<-[r2:ATE]-(you:Person)
WITH me,count(DISTINCT r1) AS H1,count(DISTINCT r2) AS H2,you
MATCH (me)-[r1:ATE]->(food)<-[r2:ATE]-(you)
RETURN SUM((1-ABS(r1.times/H1-r2.times/H2))*(r1.times+r2.times)/(H1+H2)) AS similarity
LIMIT 100;

因此,我开始研究如何将之前限制为“第一”100 人并得出以下结论:

EXPORT name="Florida Goyette"
MATCH (me:Person { name: {name} })-[r1:ATE]->(food)
WITH me, food
MATCH (food)<-[r2:ATE]-(you)
WHERE me <> you
WITH me, you
LIMIT 100
MATCH (me)-[r1:ATE]->(food)<-[r2:ATE]-(you)
WITH me, count(DISTINCT r1) AS H1, count(DISTINCT r2) AS H2, you
MATCH (me)-[r1:ATE]->(food)<-[r2:ATE]-(you)
WITH me, you, SUM((1-ABS(r1.times/H1-r2.times/H2))*(r1.times+r2.times)/(H1+H2)) AS similarity
RETURN me.name, you.name, similarity
ORDER BY similarity DESC;

但是这个查询在预热缓存上表现很差

100 rows
16038 ms

对于“实时”使用,是否有机会使此类查询执行得更快?

系统和 Neo4j

Windows 7(64 位)、Intel Core I7-2600K、8GB RAM、SSD 驱动器上的 Neo4j 数据库。

Neo4j 社区版本:2.1.0-M01(也在 2.0.1 stable 上测试过)

neo4j-community.options

 -Xmx2048m
 -Xms2048m

neo4j.properties

neostore.nodestore.db.mapped_memory=200M
neostore.relationshipstore.db.mapped_memory=200M
neostore.propertystore.db.mapped_memory=200M
neostore.propertystore.db.strings.mapped_memory=330M
neostore.propertystore.db.arrays.mapped_memory=330M

node_auto_indexing=true
node_keys_indexable=name
relationship_auto_indexing=true
relationship_keys_indexable=times

Cypher dump of my data(503kb 压缩)

PROFILE 输出

ColumnFilter(symKeys=["similarity", "you", "you.name", "me", "me.name"], returnItemNames=["me.name", "you.name", "similarity"], _rows=100, _db_hits=0)
Sort(descr=["SortItem(similarity,false)"], _rows=100, _db_hits=0)
  Extract(symKeys=["me", "you", "similarity"], exprKeys=["me.name", "you.name"], _rows=100, _db_hits=200)
    ColumnFilter(symKeys=["me", "you", "  INTERNAL_AGGREGATEcb085cf5-8982-4a83-ba3d-9642de570c59"], returnItemNames=["me", "you", "similarity"], _rows=100, _db_hits=0)
      EagerAggregation(keys=["me", "you"], aggregates=["(INTERNAL_AGGREGATEcb085cf5-8982-4a83-ba3d-9642de570c59,Sum(Divide(Multiply(Subtract(Literal(1),AbsFunction(Subtract(Divide(Property(r1,times(1)),H1),Divide(Property(r2,times(1)),H2)))),Add(Property(r1,times(1)),Property(r2,times(1)))),Add(H1,H2))))"], _rows=100, _db_hits=40000)
        SimplePatternMatcher(g="(you)-['r2']-(food),(me)-['r1']-(food)", _rows=10000, _db_hits=0)
          ColumnFilter(symKeys=["me", "you", "  INTERNAL_AGGREGATE677cd11c-ae53-4d7b-8df6-732ffed28bbf", "  INTERNAL_AGGREGATEb5eb877c-de01-4e7a-9596-03cd94cfa47a"], returnItemNames=["me", "H1", "H2", "you"], _rows=100, _db_hits=0)
            EagerAggregation(keys=["me", "you"], aggregates=["(  INTERNAL_AGGREGATE677cd11c-ae53-4d7b-8df6-732ffed28bbf,Distinct(Count(r1),r1))", "(  INTERNAL_AGGREGATEb5eb877c-de01-4e7a-9596-03cd94cfa47a,Distinct(Count(r2),r2))"], _rows=100, _db_hits=0)
              SimplePatternMatcher(g="(you)-['r2']-(food),(me)-['r1']-(food)", _rows=10000, _db_hits=0)
                ColumnFilter(symKeys=["me", "food", "you", "r2"], returnItemNames=["me", "you"], _rows=100, _db_hits=0)
                  Slice(limit="Literal(100)", _rows=100, _db_hits=0)
                    Filter(pred="NOT(me == you)", _rows=100, _db_hits=0)
                      SimplePatternMatcher(g="(you)-['r2']-(food)", _rows=100, _db_hits=0)
                        ColumnFilter(symKeys=["food", "me", "r1"], returnItemNames=["me", "food"], _rows=1, _db_hits=0)
                          Filter(pred="Property(me,name(0)) == {name}", _rows=1,_db_hits=148901)
                            TraversalMatcher(start={"label": "Person", "producer": "NodeByLabel", "identifiers": ["me"]}, trail="(me)-[r1:ATE WHERE true AND true]->(food)", _rows=148901, _db_hits=148901)

【问题讨论】:

标签: neo4j cypher


【解决方案1】:

您正在多次执行相同的 MATCHing。这样做效果更好吗?

EXPORT name="Florida Goyette"
MATCH (me:Person { name: {name}})-[r1:ATE]->(food)<-[r2:ATE]-(you:Person)
WITH me,r1,r2,count(DISTINCT r1) AS H1,count(DISTINCT r2) AS H2,you
LIMIT 100 
RETURN SUM((1-ABS(r1.times/H1-r2.times/H2))*(r1.times+r2.times)/(H1+H2)) AS similarity;

【讨论】:

  • 很遗憾没有。 1 row 361023 ms
  • 设置正确的索引后,它现在在 1400 毫秒内返回。但结果不准确。
  • 你能分享一下结果吗?
【解决方案2】:

您使用了错误的索引类型。使用

创建标签索引
CREATE INDEX ON :Person(name)

检查架构索引和约束

neo4j-shell

schema
schema ls -l :User 

neo4j 浏览器

:schema 
:schema ls -l :User

可能需要对查询进行优化,但从这里开始。

【讨论】:

  • 是的,当前版本确实找到了所有路径和过滤器。
  • 谢谢。我误读了索引文档并使用了“旧版”索引。将改变它并尝试。
【解决方案3】:
  1. 在 Windows 上,内存映射在 inside 堆中。因此,将堆大小增加到 4G。

  2. 您不需要旧的自动索引,而是需要像 jjaderberg 这样的新模式索引。

  3. 这会返回多少行?

.

MATCH (me:Person { name: {name}})-[r1:ATE]->(food)<-[r2:ATE]-(you:Person) RETURN count(*)

还有多少:

MATCH (me:Person { name: {name}})-[r1:ATE]->(food)<-[r2:ATE]-(you:Person)
WITH me,count(DISTINCT r1) AS H1,count(DISTINCT r2) AS H2,you
MATCH (me)-[r1:ATE]->(food)<-[r2:ATE]-(you)
RETURN COUNT(*)

你也可以避免匹配两次:

MATCH (me:Person { name: {name}})-[r1:ATE]->(food)<-[r2:ATE]-(you:Person)
WITH me,
     collect([r1,r2]) as rels, 
     count(DISTINCT r1) AS H1,
     count(DISTINCT r2) AS H2,
     you

RETURN me,you, 
       reduce(a=0,r in rels | 
              a + (1-ABS(r[0].times/H1-r[1].times/H2))*
                  (r[0].times+r[1].times)
                  /(H1+H2) as similarity

顺便说一句。如果您使用您的域、用例和一些示例数据创建了一个 GraphGist,那就太棒了!

【讨论】:

  • 我已将 -Xmx 和 -Xms 设置为 3072m(目前在我的笔记本电脑上)。 Windows“资源管理器”显示 Neo4j-community.exe 的提交 3.4GB 和工作集 1.3GB 我按照@jjaderberg 的建议更改了索引。第一个查询在 700 毫秒内返回 149900 行(第一次运行后)。第二个查询在 140588 毫秒内返回 149000 行(第一次运行后)。我无法让您的第三个查询工作,我收到语法异常 (SyntaxException: Invalid input '.': expected whitespace) a + (1-ABS(r[0].times/H1-r[1].times/H2))*" 错误指出:r[0].times
  • 我创建了GraphGist,这就是你的想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
相关资源
最近更新 更多