【问题标题】:Neo4j: Optimizing `WHERE` on relationship propertyNeo4j:优化关系属性的“WHERE”
【发布时间】:2017-04-14 03:34:18
【问题描述】:

这是我运行的查询:

match (n:User), 
(n) -[r]-> (p:Platform {id:"apple"}),
(n) -[l]-> (lang:Language {id: "en"}),
(n) -[photos:REL]-> (:Event {type: "photo_upload"})
return * LIMIT 30

这使用 Scheme 索引运行得非常快(30-40ms)。但是下面的速度慢了很多(>1000ms):

match (n:User), 
(n) -[r]-> (p:Platform {id:"apple"}),
(n) -[l]-> (lang:Language {id: "en"}),
(n) -[photos:REL]-> (:Event {type: "photo_upload"})
WHERE photos.count > 10
return * LIMIT 30

只有 3000 个节点与 first 查询匹配,但添加 WHERE 会将其减慢到 1 秒。我知道我们没有关系属性索引,但即便如此,天真地循环通过 3000 个节点也不会花费 1 秒,所以我猜我做错了什么,因为它似乎没有运行 WHERE匹配的节点,但在匹配之前运行。我该如何优化呢?

第一个查询的 PROFILE 计划: http://imgur.com/a/skACV

第二个的PROFILE计划: http://imgur.com/a/b6vx9

编辑:进一步调查:

当我输入SKIP 时,它变慢了很多。所以它似乎没有过滤每条路径上的匹配,而是单独匹配所有然后合并,这减慢了它的速度。有没有办法让它只匹配结果

【问题讨论】:

  • 您是否尝试过使用 PROFILE 执行查询?您能否将分析查询返回的查询计划添加到您的描述中(首先扩展计划的所有元素)?
  • @InverseFalcon 更新
  • 要明确的是,执行 2 个查询时,数据库是否准确?
  • 您真的需要 :Platform 和 :Language 的关系和节点,还是只想将它们作为谓词来过滤 :Users 返回?
  • @InverseFalcon 我只是希望它们被过滤。这种查询对我来说是标准的,每个关系可能在 WHERE 中有一个额外的过滤器

标签: optimization neo4j cypher query-optimization


【解决方案1】:

在您的 cmets 中,您观察到首先在特定的 PlatformLanguageEvent 节点上进行匹配会加快速度。那是因为这有助于将搜索集中在与那些特定节点相关的路径上。 Cypher 计划器并不总是足够复杂,无法找出最有效的计划,因此有时您必须帮助它。

如果您在:Platform(id):Language(id):Event(type) 上创建了索引(或唯一性约束),则以下查询应该是有效的。

MATCH (p:Platform {id:"apple"}), (lang:Language {id: "en"}), (e:Event {type: "photo_upload"})
USING INDEX p:Platform(id)
USING INDEX lang:Language(id)
USING INDEX e:Event(type)
MATCH (n:User)-[r]->(p), (n)-[l]->(lang), (n)-[photos:REL]->(e)
WHERE photos.count > 10
RETURN *
LIMIT 30

请注意,我必须向 Cypher 规划器提供 3 个单独的提示以使用 3 个索引(或唯一性约束),因为规划器似乎更喜欢自己最多使用一个索引。如果您使用所有 3 个索引来快速获取 3 个节点以开始搜索,您应该会获得最快的结果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-14
    • 1970-01-01
    相关资源
    最近更新 更多