neo4j查询的复杂性

时间:2018-09-12 10:08:17

标签: neo4j cypher cypher-3.1

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

例如:

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 

我尝试了 profile&解释子句,但它们仅返回数据库命中数。是否可以为neo4j查询获得较大的注释,即我们用大的O注释来衡量性能?除了使用个人资料和解释之外,还有其他方法可以检查查询性能吗?

3 个答案:

答案 0 :(得分:1)

不,您不能将Cypher转换为Big O表示法。

Cypher不会描述如何获取信息,而只描述您想返回的信息类型。由Neo4j数据库中的Cypher计划者将Cypher转换为可执行查询(使用启发式方法来查找必须查找的信息,可用的索引以及有关要查询的数据集的内部统计信息。因此只需更改数据库的状态可能会更改Cypher的复杂性。)

Cypher Cypher 3.1 MATCH (a{id:1})-[*0..25]->(b) RETURN DISTINCT b是一个非常简单的例子。使用带有循环的相当平均的连接图,针对Neo4j 3.1.1的运行会因为过于复杂而超时(因为计划程序会尝试找到所有路径,即使它不需要多余的信息),而Neo4j 3.2.3则会超时返回非常快(因为Planner认识到它只需要进行深度优先搜索之类的图形扫描即可找到所有连接的节点)。


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

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

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

答案 1 :(得分:0)

PROFILE结果向您显示neo4j服务器实际上是如何计划处理您的Cypher查询的。您需要分析PROFILE结果揭示的执行计划,以获取大的O复杂度。我不知道有什么工具可以做(尽管创建一个人是一个好主意)。

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

答案 2 :(得分:0)

没有任何东西很容易获得。但是可以通过一些额外的努力来得出/近似它。

在分析查询时,我们获得了neo4j将运行以实现所需结果的功能列表。 从理论上讲,每个功能都将与最坏到最好的情况相关。其中一些也将并行运行。这将影响运行时,具体取决于服务器具有的内核。

例如,匹配(a:A)匹配(a:B)得出笛卡尔积。这将是O(count(a)* count(b))

类似地,查询计划中的每个功能确实具有这种时间复杂性。

因此,这些函数的各个时间复杂度的汇总将为您提供查询时间复杂度的整体近似值。

但是随着neo4j的每个版本的出现,这种情况会不时发生变化,因为它们的社区可以随时更改查询的植入方式,或者实现更好的运行时间/结构更改/并行化/减少ram的使用。

如果您正在寻找的是Neo4j查询优化的指示,那么db-hits是一个很好的指示。