neo4j 查询的复杂性



我需要测量任何查询的性能。

例如:

MATCH (n:StateNode)-[r:has_city]->(n1:CityNode)
WHERE n.shortName IN {0} and n1.name IN {1} 
WITH n1
Match (aa:ActiveStatusNode{isActive:toBoolean('true')})--(n2:PannaResume)-[r1:has_location]->(n1)
WHERE (n2.firstName="master") OR (n2.lastName="grew" )
WITH n2  
MATCH (o:PannaResumeOrganizationNode)<-[h:has_organization]-(n2)-[r2:has_skill]->(n3:Skill)
WHERE (0={3} OR o.organizationId={3}) AND (0={4} OR n3.name IN {2} OR n3.name IN {5}) 
WITH size(collect(n3)) as count, n2 
MATCH (n2) where (0={4} OR count={4}) 
RETURN DISTINCT n2 

我尝试了配置文件和解释子句,但它们只返回 db 命中数。是否可以为 neo4j 查询获得大符号,即我们用大 O 符号来衡量性能?除了使用配置文件和解释之外,还有其他方法可以检查查询性能吗?

不,您不能将密码转换为大O表示法。

Cypher没有描述如何获取信息,只描述你想要返回什么样的信息。由Neo4j数据库中的Cypher规划器将Cypher转换为可执行查询(使用启发式方法,了解它必须找到哪些信息,哪些索引可供它使用,以及有关正在查询的数据集的内部统计信息。因此,简单地更改数据库的状态可以改变密码的复杂性。

一个非常简单的例子是 密码Cypher 3.1 MATCH (a{id:1})-[*0..25]->(b) RETURN DISTINCT b.使用一个相当平均的连接图和周期,运行 Neo4j 3.1.1 会因为太复杂而超时(因为规划器试图找到所有路径,即使它不需要冗余信息(,而 Neo4j 3.2.3 会很快返回(因为规划器认识到它只需要像深度优先搜索一样进行图形扫描来查找所有连接的节点(。


旁注,您可以在返回结果上争论 BIG O 符号。例如MATCH (a), (b)必须具有 n^2 的最小复杂度,因为结果是笛卡尔积,并且执行不能比答案复杂。这种对复杂性如何影响行计数的理解可以帮助您编写 Cyphers,从而减少 Planner 最终计划的工作量。

例如,使用WITH COLLECT(n) as data MATCH (c:M)将计划程序最终在 Cypher 的下一部分之前执行的工作的行数从 nm(第一个匹配计数乘以第二个匹配计数(减少到 m(1 次第二个匹配计数(。

但是,由于Cypher没有对如何找到数据做出任何承诺,因此无法保证执行的复杂性。我们只能尝试编写更有可能获得最佳执行计划的 Cyphers,并使用 EXPLAIN/PROFILE 来评估计划者是否能够找到相对最优的解决方案。

PROFILE 结果显示了 neo4j 服务器实际计划如何处理您的 Cypher 查询。您需要分析 PROFILE 结果揭示的执行计划才能获得大 O 复杂度。我知道没有工具可以做到这一点(尽管有人创建一个是个好主意(。

您还应该知道,随着数据库特征的变化,以及更改为不同版本的 neo4j 时,查询的执行计划可能会随时间而变化。

这些都不是现成的。 但它可以通过一些额外的努力来推导出/近似。

在分析查询时,我们得到一个函数列表,neo4j 将运行这些函数以实现所需的结果。 理论上,此函数中的每一个都将与最坏到最佳的情况复杂性相关联。其中一些也将并行运行。这将影响运行时,具体取决于服务器具有的核心。

例如,匹配 (a:A( 匹配 (a:B( 会产生笛卡尔积。这将是 O(count(a(*count(b((

同样,查询计划中的每个函数确实具有这样的时间复杂性。

因此,这些函数的这种单独时间复杂度的聚合将为您提供查询的时间复杂度的总体近似值。

但是随着每个版本的neo4j,这将不时改变,因为他们社区总是可以改变查询的植入或实现更好的运行时/结构更改/并行化/更少的ram使用。

如果您正在寻找的是 neo4j 查询 db-hit 优化的指示,这是一个很好的指标。

最新更新