【问题标题】:Improve Neo4j Cypher Performance On Lengthy Match提高 Neo4j Cypher 在长时间匹配时的性能
【发布时间】:2013-11-22 20:39:46
【问题描述】:

设置:

  • Neo4j - 1.9.3
  • ~7,000 个节点
  • ~180 万关系

我有以下想要提高性能的密码查询:

START a=node(2) MATCH (a)-[:knowledge]-(x)-[:depends]-(y)-[:knowledge]-(end) RETURN COUNT(DISTINCT end);

这将返回 471(188171 毫秒)。

现在我只得到一个计数,但稍后我可能想要获取值(本例中为 471)。问题是运行大约需要 3-4 分钟。

该图与许多关系高度相关。运行以下命令显示节点 a(2) 存在多少条“知识”类型的边。

START a=node(2) MATCH (a)-[:knowledge]-(x) RETURN COUNT(a);

这将返回 4350(103 毫秒)。

对我来说,这似乎没有太多需要检查的地方。我可以以某种方式拆分它以提高性能吗?

编辑:根据 cmets,以下是使用配置文件运行查询的结果:

profile START a=node(2) MATCH (a)-[:knowledge]-(x)-[:depends]-(y)-[:knowledge]-(end) RETURN COUNT(DISTINCT end);
==> +---------------------+
==> | COUNT(DISTINCT end) |
==> +---------------------+
==> | 471                 |
==> +---------------------+
==> 1 row
==> 
==> ColumnFilter(symKeys=["  INTERNAL_AGGREGATEcd2aff18-1c9d-47a8-9217-588cb86bbc1a"], returnItemNames=["COUNT(DISTINCT end)"], _rows=1, _db_hits=0)
==> EagerAggregation(keys=[], aggregates=["(  INTERNAL_AGGREGATEcd2aff18-1c9d-47a8-9217-588cb86bbc1a,Distinct)"], _rows=1, _db_hits=0)
==>   TraversalMatcher(trail="(a)-[  UNNAMED7:knowledge WHERE true AND true]-(x)-[  UNNAMED8:depends WHERE true AND true]-(y)-[  UNNAMED9:knowledge WHERE true AND true]-(end)", _rows=25638262, _db_hits=25679365)
==>     ParameterPipe(_rows=1, _db_hits=0)

【问题讨论】:

  • 你可以添加路线,还是不应该指导?
  • 4350 不是很多,但如果 (x)-[:depends]-(y)(y)-[:knowledge]-(end) 匹配一样多,则您有 82312875000 个路径。在与节点有许多关系的图中,韦斯所说的指定方向对于排除不相关的路径可能特别有帮助。您可能希望在 webadmin 中运行带有 PROFILE 前缀的查询,并查看(在此处发布)执行计划,该计划将显示在查询的每个步骤中维护了多少匹配(行)。另外,请尝试在不使用 DISTINCT 的情况下返回,以查看实际匹配了多少 end
  • 在这种情况下我并没有真正使用方向,所以我不相信我可以对此进行优化。我已经用个人资料结果更新了我的帖子。如您所见,有近 2600 万次点击,需要整理的内容很多。我的另一种选择是添加一个额外的边缘类型,这样 :knowledge 部分将只有一个单独的边缘。这意味着添加不必要的数据,但如果我需要它来提高性能,这可能是值得的。

标签: neo4j cypher


【解决方案1】:

我最终做了以下事情来提高性能:

profile START a=node(2) MATCH (a)-[:knowledge]-(x) WITH DISTINCT x MATCH (x)-[:depends]-(y) WITH DISTINCT y MATCH (y)-[:knowledge]-(end) WITH DISTINCT end RETURN COUNT(end);
==> +------------+
==> | COUNT(end) |
==> +------------+
==> | 471        |
==> +------------+
==> 1 row
==> 
==> ColumnFilter(symKeys=["  INTERNAL_AGGREGATE1967576a-d357-457a-b799-adbb16b93048"], returnItemNames=["COUNT(end)"], _rows=1, _db_hits=0)
==> EagerAggregation(keys=[], aggregates=["(  INTERNAL_AGGREGATE1967576a-d357-457a-b799-adbb16b93048,Count)"], _rows=1, _db_hits=0)
==>   Distinct(_rows=471, _db_hits=0)
==>     PatternMatch(g="(end)-['  UNNAMED3']-(y)", _rows=403437, _db_hits=0)
==>       Distinct(_rows=735, _db_hits=0)
==>         PatternMatch(g="(x)-['  UNNAMED2']-(y)", _rows=1653, _db_hits=0)
==>           Distinct(_rows=177, _db_hits=0)
==>             TraversalMatcher(trail="(a)-[  UNNAMED1:knowledge WHERE true AND true]-(x)", _rows=4350, _db_hits=4351)
==>               ParameterPipe(_rows=1, _db_hits=0)

通过使每个步骤成为整体的一小部分,它降低了整体的复杂性,并且只遵循将匹配的边缘。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多