统计信息和执行计划

当提交 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

10s

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

手动重新计划

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

db.clearQueryCaches()

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

CALL db.clearQueryCaches()
db.prepareForReplanning()

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

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

CALL db.prepareForReplanning()

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

有关更多信息,请参阅