

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Amazon Neptune 中的查询计划缓存
<a name="access-graph-qpc"></a>

 查询提交至 Neptune 时，查询字符串会被解析、优化并转换为查询计划，然后由引擎执行。应用程序通常依赖通用查询模式，这些模式会通过传入不同参数值来实例化。查询计划缓存可以通过缓存查询计划，避免对此类重复的模式进行解析和优化，从而降低整体延迟。

 Query Plan Cache 可用于**OpenCypher**查询，包括非参数化查询或参数化查询。READ（包括 HTTP 和 Bolt）支持该功能。OC 突变查询**不**支持该功能。Gremlin 或 SPARQL 查询**不**支持该功能。

## 如何强制启用或禁用查询计划缓存
<a name="access-graph-qpc-enable"></a>

 默认情况下，查询计划缓存处于启用状态，用于低延迟参数化查询。仅当延迟低于 **100 毫秒**的阈值时，系统才会缓存参数化查询的计划。查询级别的查询提示 `QUERY:PLANCACHE` 可以在每个查询（无论是否参数化）的基础上覆盖此行为。它需要与 `USING` 子句一起使用。该查询提示接受 `enabled` 或 `disabled` 作为值。

```
# Forcing plan to be cached or reused
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" MATCH(n) RETURN n LIMIT 1"
  
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
  -d "parameters={\"arg\": 123}"
  
# Forcing plan to be neither cached nor reused
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"disabled\" MATCH(n) RETURN n LIMIT 1"
```

## 如何确定计划是否已缓存
<a name="access-graph-qpc-status"></a>

 对于 HTTP READ，如果已提交查询且计划已缓存，则 `explain` 将显示与查询计划缓存相关的详细信息。

```
% curl -k https://<endpoint>:<port>/opencypher \
  -d "query=Using QUERY:PLANCACHE \"enabled\" MATCH(n) RETURN n LIMIT 1" \
  -d "explain=[static|details]"

Query: <QUERY STRING>
Plan cached by request: <REQUEST ID OF FIRST TIME EXECUTION>
Plan cached at: <TIMESTAMP OF FIRST TIME EXECUTION>
Parameters: <PARAMETERS, IF QUERY IS PARAMETERIZED QUERY>
Plan cache hits: <NUMBER OF CACHE HITS FOR CACHED PLAN>
First query evaluation time: <LATENCY OF FIRST TIME EXECUTION>

The query has been executed based on a cached query plan. Detailed explain with operator runtime statistics can be obtained by running the query with plan cache disabled (using HTTP parameter planCache=disabled).
```

 使用 Bolt 时，不支持解释功能。

## 驱逐
<a name="access-graph-qpc-eviction"></a>

 当达到缓存生存时间（TTL）或缓存查询计划的最大数量时，查询计划将被驱逐。当查询计划被命中时，TTL 会刷新。默认值为：
+  1000 – 每个实例可以缓存的最大计划数。
+  TTL – 30 万毫秒或 5 分钟。缓存命中会重新启动 TTL，并将其重置回 5 分钟。

## 导致计划无法缓存的条件
<a name="access-graph-qpc-conditions"></a>

 在以下条件下，系统不会使用查询计划缓存：

1.  使用查询提示 `QUERY:PLANCACHE "disabled"` 提交查询。您可以重新运行查询并删除 `QUERY:PLANCACHE "disabled"` 以启用查询计划缓存。

1.  提交的查询不是参数化查询且不包含提示 `QUERY:PLANCACHE "enabled"`。

1.  如果查询评估时间大于延迟阈值，则该查询不会被缓存，并且被视为长时查询，不会使用查询计划缓存。

1.  查询包含不返回任何结果的模式。
   +  例如 `MATCH (n:nonexistentLabel) return n`（当具有指定标签的节点为零时）。
   +  例如带有 `parameters={"param": "abcde"}` 的 `MATCH (n {name: $param}) return n`（当包含 `name=abcde` 的节点为零时）。

1.  查询参数是复合类型，例如 `list` 或 `map`。

   ```
   curl -k https://<endpoint>:<port>/opencypher \
     -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
     -d "parameters={\"arg\": [1, 2, 3]}"
   
   curl -k https://<endpoint>:<port>/opencypher \
     -d "query=Using QUERY:PLANCACHE \"enabled\" RETURN \$arg" \
     -d "parameters={\"arg\": {\"a\": 1}}"
   ```

1.  查询参数是一个未参与数据加载或数据插入操作的字符串。例如，如果运行 `CREATE (n {name: "X"})` 以插入 `"X"`，则 `RETURN "X"` 会被缓存，而 `RETURN "Y"` 不会被缓存，因为 `"Y"` 尚未插入且不在数据库中。