

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

# Gremlin 查询提示
<a name="gremlin-query-hints"></a>

您可使用查询提示为 Amazon Neptune 中的特定 Gremlin 查询指定优化和计算策略。

通过使用以下语法向查询添加 `withSideEffect` 步骤来指定查询提示。

```
g.withSideEffect(hint, value)
```
+ *hint* – 确定要应用的提示的类型。
+ *value* – 确定要考虑的系统方面的行为。

例如，以下示例为如何在 Gremlin 遍历中包含 `repeatMode` 提示。

**注意**  
所有 Gremlin 查询提示副作用的前缀为 `Neptune#`。

```
g.withSideEffect('Neptune#repeatMode', 'DFS').V("3").repeat(out()).times(10).limit(1).path()
```

上述查询指示 Neptune 引擎遍历图形时要*深度优先* (`DFS`)，而不是默认的 Neptune *广度优先* (`BFS`)。

以下各节提供了可用查询提示及其用法的更多信息。

**Topics**
+ [Gremlin repeatMode 查询提示](gremlin-query-hints-repeatMode.md)
+ [Gremlin noReordering 查询提示](gremlin-query-hints-noReordering.md)
+ [Gremlin typePromotion 查询提示](gremlin-query-hints-typePromotion.md)
+ [Gremlin useDFE 查询提示](gremlin-query-hints-useDFE.md)
+ [使用结果缓存的 Gremlin 查询提示](gremlin-query-hints-results-cache.md)

# Gremlin repeatMode 查询提示
<a name="gremlin-query-hints-repeatMode"></a>

Neptune `repeatMode` 查询提示指定 Neptune 引擎计算 Gremlin 遍历中的 `repeat()` 步骤的方式：广度优先、深度优先或分块深度优先。

在使用 `repeat()` 步骤查找或跟踪路径时，该步骤的计算模式非常重要，而不只是将步骤重复有限次数。

## 语法
<a name="gremlin-query-hints-repeatMode-syntax"></a>

通过向查询添加 `withSideEffect` 步骤来指定 `repeatMode` 查询提示。

```
g.withSideEffect('Neptune#repeatMode', 'mode').gremlin-traversal
```

**注意**  
所有 Gremlin 查询提示副作用的前缀为 `Neptune#`。

**可用模式**
+ `BFS`

  广度优先搜索

  `repeat()` 步骤的默认执行模式。这将在沿路径深入之前获取所有同级节点。

  此版本为内存密集型的，边界可以非常大。查询将耗尽内存并被 Neptune 引擎取消的风险更高。这与其他 Gremlin 实施最匹配。
+ `DFS`

  深度优先搜索

  在继续下一个解之前，跟踪每条路径至最大深度。

  这将使用更少的内存。在类似从多个跃点外的起点查找单一路径这样的情况下，它可提供更好的性能。
+ `CHUNKED_DFS`

  分块深度优先搜索

  一种混合方式，它在 1000 个节点（既不是 1 个节点 (`DFS`) ，也不是所有节点 (`BFS)`) ）组成的区块中，以深度优先方式搜索图形。

  Neptune 引擎将在每个级别获得多达 1000 个节点，然后更深入地跟踪该路径。

  这是一种速度和内存使用率之间的平衡方法。

  如果您要使用 `BFS`，但查询占用的内存太多，这也会很有用。



## 示例
<a name="gremlin-query-hints-repeatMode-example"></a>

以下各节介绍了重复模式对 Gremlin 遍历的影响。

在 Neptune 中，`repeat()` 步骤的默认模式是对所有遍历实施广度优先 (`BFS`) 执行策略。

在大多数情况下， TinkerGraph 实现使用相同的执行策略，但在某些情况下，它会改变遍历的执行。

例如， TinkerGraph 实现修改了以下查询。

```
g.V("3").repeat(out()).times(10).limit(1).path()
```

此遍历中的 `repeat()` 步骤将“展开”到以下遍历，这将导致执行深度优先 (`DFS`) 策略。

```
g.V(<id>).out().out().out().out().out().out().out().out().out().out().limit(1).path()
```

**重要**  
Neptune 查询引擎不会自动执行此操作。

广度优先 (`BFS`) 是默认的执行策略，与大多数 TinkerGraph 情况下的执行策略类似。但是，在特定情况下会优先选择深度优先 (`DFS`) 策略。

 

**BFS（默认）**  
广度优先 (BFS) 是 `repeat()` 运算符的默认执行策略。

```
g.V("3").repeat(out()).times(10).limit(1).path()
```

Neptune 引擎将完全探索前九个跃点边界，然后再向外扩展十个跃点查找解。这在许多情况（如最短路径查询）下很有效率。

但是，对于上述示例，遍历使用 `repeat()` 运算符的深度优先 (`DFS`) 模式将快得多。

**DFS**  
以下查询使用 `repeat()` 运算符的深度优先 (`DFS`) 模式。

```
g.withSideEffect("Neptune#repeatMode", "DFS").V("3").repeat(out()).times(10).limit(1)
```

在探索下一个解之前，这将跟踪每个单独的解，直至最大深度。

# Gremlin noReordering 查询提示
<a name="gremlin-query-hints-noReordering"></a>

在提交 Gremlin 遍历时，Neptune 查询引擎将调查遍历的结构并对查询的各个部分重新排序，尝试最大程度地减少计算所需的工作量和查询响应时间。例如，具有多个约束的遍历（如多个 `has()` 步骤）通常不会按给定顺序进行计算。相反，它在使用静态分析检查查询之后进行重新排序。

Neptune 查询引擎尝试确定哪个约束更适合选择并最先运行该约束。这通常会实现更高的性能，但 Neptune 选择计算查询的顺序可能并不总是最佳的。

如果您知道确切的数据特性并且想要手动指示查询执行顺序，请使用 Neptune `noReordering` 查询提示指定按给定顺序计算遍历。

## 语法
<a name="gremlin-query-hints-noReordering-syntax"></a>

通过向查询添加 `withSideEffect` 步骤来指定 `noReordering` 查询提示。

```
g.withSideEffect('Neptune#noReordering', true or false).gremlin-traversal
```

**注意**  
所有 Gremlin 查询提示副作用的前缀为 `Neptune#`。

**可用值**
+ `true`
+ `false`

# Gremlin typePromotion 查询提示
<a name="gremlin-query-hints-typePromotion"></a>

当您提交根据数值或范围进行筛选的 Gremlin 遍历时，Neptune 查询引擎在执行查询时通常必须使用类型提升。这意味着它必须检查每种类型的值，这些值可能包含您正在筛选的值。

例如，如果要筛选等于 55 的值，则引擎必须查找等于 55 的整数、等于 55L 的长整数、等于 55.0 的浮点数，依此类推。每个类型提升都需要在存储上进行额外查找，这可能会导致看似简单的查询需要意想不到的长时间才能完成。

假设您正在搜索所有客户年龄属性大于 5 的顶点：

```
g.V().has('customerAge', gt(5))
```

要彻底执行该遍历，Neptune 必须扩展查询，以检查您要查询的值可以提升到的所有数字类型。在这种情况下，必须对任何大于 5 的整数、任何超过 5L 的长整数、任何超过 5.0 的浮点数以及任何大于 5.0 的双精度数应用 `gt` 筛选条件。由于每种类型提升都需要在存储空间上进行额外查找，因此，当您针对此查询运行 [Gremlin `profile` API](gremlin-profile-api.md) 时，您会看到每个数字筛选条件都有多个筛选条件，而且完成所需的时间将比您预期的要长得多。

通常没有必要进行类型提升，因为您事先知道只需要查找一种特定类型的值即可。在这种情况下，您可以使用 `typePromotion` 查询提示来关闭类型提升，从而大大加快查询速度。

## 语法
<a name="gremlin-query-hints-typePromotion-syntax"></a>

通过向查询添加 `withSideEffect` 步骤来指定 `typePromotion` 查询提示。

```
g.withSideEffect('Neptune#typePromotion', true or false).gremlin-traversal
```

**注意**  
所有 Gremlin 查询提示副作用的前缀为 `Neptune#`。

**可用值**
+ `true`
+ `false`

要关闭上述查询的类型提升，您可以使用：

```
g.withSideEffect('Neptune#typePromotion', false).V().has('customerAge', gt(5))
```

# Gremlin useDFE 查询提示
<a name="gremlin-query-hints-useDFE"></a>

使用此查询提示可以启用 DFE 来执行查询。默认情况下，如果不将此查询提示设置为 `true`，Neptune 就不会使用 DFE，因为 [neptune\$1dfe\$1query\$1engine](parameters.md#parameters-instance-parameters-neptune_dfe_query_engine) 实例参数默认为 `viaQueryHint`。如果将该实例参数设置为 `enabled`，则除 `useDFE` 查询提示设置为 `false` 的查询外，所有查询都将使用 DFE 引擎。

为查询启用 DFE 的示例：

```
g.withSideEffect('Neptune#useDFE', true).V().out()
```

# 使用结果缓存的 Gremlin 查询提示
<a name="gremlin-query-hints-results-cache"></a>

启用[查询结果缓存](gremlin-results-cache.md)后，可以使用以下查询提示。

## Gremlin `enableResultCache` 查询提示
<a name="gremlin-query-hints-results-cache-enableResultCache"></a>

如果查询结果已被缓存，则值为 `true` 的 `enableResultCache` 查询提示会使查询结果从缓存中返回。否则，它将返回新的结果并缓存它们，直到从缓存中清除它们。例如：

```
g.with('Neptune#enableResultCache', true)
 .V().has('genre','drama').in('likes')
```

稍后，您可以通过再次发出完全相同的查询来访问缓存的结果。

如果此查询提示的值为 `false`，或者它不存在，则不会缓存查询结果。但是，将其设置为 `false` 不会清除现有的缓存结果。要清除缓存的结果，请使用 `invalidateResultCache` 或 `invalidateResultCachekey` 提示。

## Gremlin `enableResultCacheWithTTL` 查询提示
<a name="gremlin-query-hints-results-cache-enableResultCacheWithTTL"></a>

`enableResultCacheWithTTL` 查询提示还会返回缓存结果（如果有），而不影响缓存中已有结果的 TTL。如果当前没有缓存结果，则查询会返回新结果并将其缓存由 `enableResultCacheWithTTL` 查询提示指定的生存时间 (TTL)。该生存时间以秒为单位指定。例如，以下查询将生存时间指定为六十秒：

```
g.with('Neptune#enableResultCacheWithTTL', 60)
 .V().has('genre','drama').in('likes')
```

在 60 秒 time-to-live结束之前，您可以使用带有`enableResultCache`或`enableResultCacheWithTTL`查询提示的相同查询（此处`g.V().has('genre','drama').in('likes')`）来访问缓存的结果。

**注意**  
用 `enableResultCacheWithTTL` 指定的生存时间不会影响已经缓存的结果。  
如果之前使用 `enableResultCache` 缓存结果，则必须先显式清除缓存，然后 `enableResultCacheWithTTL` 才能生成新结果并将结果缓存达它指定的 TTL。
如果之前使用 `enableResultCachewithTTL` 缓存结果，则该先前的 TTL 必须先过期，然后 `enableResultCacheWithTTL` 才能生成新结果并将结果缓存达它指定的 TTL。

生存时间过后，查询的缓存结果将被清除，同一查询的后续实例随后会返回新的结果。如果 `enableResultCacheWithTTL` 附加到该后续查询，则新结果将使用它指定的 TTL 进行缓存。

## Gremlin `invalidateResultCacheKey` 查询提示
<a name="gremlin-query-hints-results-cache-invalidateResultCacheKey"></a>

`invalidateResultCacheKey` 查询提示可以取 `true` 或 `false` 值。`true` 值会导致 `invalidateResultCacheKey` 附加到的查询的缓存结果被清除。例如，以下示例会导致为查询键 `g.V().has('genre','drama').in('likes')` 缓存的结果被清除：

```
g.with('Neptune#invalidateResultCacheKey', true)
 .V().has('genre','drama').in('likes')
```

上面的示例查询不会导致其新结果被缓存。如果要在清除现有缓存结果后缓存新结果，则可以在同一个查询中包含 `enableResultCache`（或 `enableResultCacheWithTTL`）：

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#invalidateResultCacheKey', true)
 .V().has('genre','drama').in('likes')
```

## Gremlin `invalidateResultCache` 查询提示
<a name="gremlin-query-hints-results-cache-invalidateResultCache"></a>

`invalidateResultCache` 查询提示可以取 `true` 或 `false` 值。`true` 值会导致结果缓存中的所有结果都被清除。例如：

```
g.with('Neptune#invalidateResultCache', true)
 .V().has('genre','drama').in('likes')
```

上面的示例查询不会导致其结果被缓存。如果要在完全清除现有缓存后缓存新结果，则可以在同一个查询中包含 `enableResultCache`（或 `enableResultCacheWithTTL`）：

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#invalidateResultCache', true)
 .V().has('genre','drama').in('likes')
```

## Gremlin `numResultsCached` 查询提示
<a name="gremlin-query-hints-results-cache-numResultsCached"></a>

`numResultsCached` 查询提示只能用于包含 `iterate()` 的查询，它指定要为它附加到的查询缓存的最大结果数。请注意，不会返回当 `numResultsCached` 存在时缓存的结果，而只缓存这些结果。

例如，以下查询指定最多应缓存 100 个结果，但不返回其中任何缓存结果：

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#numResultsCached', 100)
 .V().has('genre','drama').in('likes').iterate()
```

然后，您可以使用如下所示的查询来检索一定范围的缓存结果（此处为前十个）：

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#numResultsCached', 100)
 .V().has('genre','drama').in('likes').range(0, 10)
```

## Gremlin `noCacheExceptions` 查询提示
<a name="gremlin-query-hints-results-cache-noCacheExceptions"></a>

`noCacheExceptions` 查询提示可以取 `true` 或 `false` 值。`true` 值会导致抑制与结果缓存相关的所有异常。例如：

```
g.with('Neptune#enableResultCache', true)
 .with('Neptune#noCacheExceptions', true)
 .V().has('genre','drama').in('likes')
```

特别是，这会抑制 `QueryLimitExceededException`，如果查询的结果太大而无法容纳在结果缓存中，则会引发该异常。