知识库

理解 Neo4j 查询计划缓存

本文基于 Neo4j 2.3.2 的行为。查询计划缓存由三个参数控制,这些参数在 conf/neo4j.properties 文件中定义,详情请参见 此处

控制 Cypher 语句是否计划/重新计划的三个参数是

  • query_cache_size

  • dbms.cypher.min_replan_interval

  • dbms.cypher.statistics_divergence_threshold

query_cache_size - 默认值为 1000,表示缓存中记录的查询计划数量。例如,如果你重新启动了 Neo4j 并运行了 1001 个唯一的 Cypher 语句,那么每个语句都会被计划,最后 1000 个会被记录在查询计划缓存中。如果你然后重新运行第一个 Cypher 语句,它将被重新计划,因为它不再在查询缓存中,因为只有 Cypher 语句 2 到 1001 当前在缓存中。

dbms.cypher.min_replan_interval - 默认值为 1 秒,描述 Cypher 语句在缓存中存在的时间,在此之后它将被重新计划。例如,如果一个 Cypher 语句在 09:02:00 被计划,而 dbms.cypher.min_replan_interval 被定义为 5 秒,那么在 09:02:01 重新提交相同的 Cypher 语句不会导致重新计划。直到 09:02:06,Cypher 语句才符合重新计划的条件。

dbms.cypher.statistics_divergence_threshold - 默认值为 0.5(值为 0 到 1 之间的数字),描述与 Cypher 相关的对象的统计信息的变化百分比,这将强制重新计划。例如,如果超过 50% 的带有标签 Movie 的节点被更改,那么运行涉及该标签的 Cypher 语句会导致重新计划。但是,运行不涉及标签 Movie 的 Cypher 语句不会导致重新计划。

关于查询缓存,你还应该了解以下内容

  • 如果存在任何模式更改,无论是通过添加/删除索引还是约束,所有查询计划都会立即失效。

  • Cypher 支持使用参数进行查询。这意味着开发人员不必诉诸字符串构建来创建查询。

  • 除此之外,它还使 Cypher 的执行计划缓存变得更加容易。

更多详细信息请参见 此处

此外,如果你在 graph.db/messages.log 中看到类似于以下内容的消息

2016-03-08 09:43:16.854+0000 INFO [o.n.c.i.ServerExecutionEngine] Discarded stale query from the query cache: CYPHER 2.3 match n return n ... ... ...

这表示之前在查询计划缓存中的计划已经重新计划。如果查询计划之前从未生成过,则不会遇到此消息。

要使此消息出现,必须满足以下条件

a) 至少必须在再次看到查询之间发生一个事务
b) 至少必须经过 dbms.cypher.min_replan_interval
c) 查询使用的统计信息的超过 dbms.cypher.statistics_divergence_threshold 百分比必须发生变化(已编辑)

例如,要生成以上消息,可以定义

dbms.cypher.min_replan_interval=0s
dbms.cypher.statistics_divergence_threshold=0

如果你按以下顺序发出 2 个 Cypher 语句 X 和 Y

  1. 语句 1:X

  2. 语句 2:Y

  3. 语句 3:X

并且 Y 修改了 X 使用的统计信息,那么我们将在 messages.log 中看到上面的消息。

例如,如果语句 X 是 MATCH n RETURN n 并且语句 Y 是 CREATE (),那么

  1. 语句 1 会将 X 放入查询缓存

  2. 语句 2 会将 Y 放入查询缓存

  3. 语句 3 会重新计划语句 X,因为

已超过 dbms.cypher.min_replan_interval,并且语句 Y 更改了语句 X 使用的统计信息