统计信息和执行计划

当Cypher查询发出时,它会被编译成一个可运行并回答查询的执行计划。Cypher查询引擎会利用数据库中的可用信息,例如关于数据库中存在哪些索引和约束的模式信息。本页介绍如何配置Neo4j统计信息收集和Cypher查询引擎中的查询重新规划。

Neo4j还利用数据库的统计信息来优化执行计划。欲了解更多信息,请参阅 Cypher手册 → 查询调优Cypher手册 → 执行计划

配置统计信息收集

Cypher查询规划器依赖于准确的统计信息来创建高效的计划。因此,这些统计信息会随着数据库的演变而保持最新。

对于DBMS中的每个数据库,Neo4j会收集以下统计信息并保持其最新状态:

对于图实体
  • 具有特定标签的节点数量。

  • 按类型划分的关系数量。

  • 具有特定标签的节点之间按类型划分的关系数量。

当您从节点设置或移除标签时,这些数字会更新。

对于数据库模式
  • 每个索引的选择性。

为了生成选择性数字,Neo4j会在后台运行完整的索引扫描。由于这可能是一个非常耗时的操作,因此只有当更改的数据达到指定阈值时,才会触发完整的索引扫描。

自动统计信息收集

您可以通过配置以下设置来控制是否以及多久自动收集一次统计信息:

参数名称 默认值 描述

db.index_sampling.background_enabled

true

启用自动(后台)索引采样。

db.index_sampling.update_percentage

5

触发给定索引采样前所需的总索引大小的索引更新百分比。

手动统计信息收集

您可以使用内置过程 db.resampleIndex()db.resampleOutdatedIndexes() 手动触发索引重新采样。

db.resampleIndex()

触发指定索引的重新采样。

CALL db.resampleIndex("indexName")
db.resampleOutdatedIndexes()

触发所有过期索引的重新采样。

CALL db.resampleOutdatedIndexes()

配置执行计划的重新规划

执行计划会被缓存,并且只有当用于生成该计划的统计信息发生变化时,才会重新规划。

自动重新规划

您可以通过配置以下设置来控制重新规划对数据库更新的敏感度:

参数名称 默认值 描述

dbms.cypher.statistics_divergence_threshold

0.75

统计信息阈值,超出该阈值则认为计划已过期。
当执行计划的基础统计信息的变化达到指定阈值时,该计划被认为是过期的,并会重新规划。变化量按 abs(a-b)/max(a,b) 计算。
这意味着值为 0.75 时,数据库需要大约增大四倍才会发生重新规划。值为 0 表示一旦统计信息发生变化且重新规划间隔结束,查询就会立即重新规划。

dbms.cypher.min_replan_interval

10秒

两次查询重新规划执行之间的最短时间。在此时间之后,会评估图统计信息,如果其变化量超过 dbms.cypher.statistics_divergence_threshold 中设置的值,则会重新规划查询。每次评估统计信息时,分歧阈值都会降低,直到大约7小时后达到10%。这确保了即使是适度变化的数据库也能在足够长的时间间隔后看到查询重新规划。

手动重新规划

您可以使用以下内置过程手动强制数据库重新规划缓存中已有的执行计划:

db.clearQueryCaches()

清除所有查询缓存。不更改数据库统计信息。

CALL db.clearQueryCaches()
db.prepareForReplanning()

完全重新计算所有数据库统计信息,以用于后续的任何查询规划。

该过程会触发索引重新采样,等待其完成,并清除所有查询缓存。之后,查询会根据最新的数据库统计信息进行规划。

CALL db.prepareForReplanning()

您可以使用Cypher重新规划来指定是否要强制重新规划(即使计划根据规划规则是有效的),或者如果您希望使用已存在的有效计划,则完全跳过重新规划。

欲了解更多信息,请参阅: