

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# Amazon Neptune Gremlin でクエリ結果をキャッシュする
<a name="gremlin-results-cache"></a>

Amazon Neptune は、Gremlin クエリの結果キャッシュをサポートしています。

クエリ結果キャッシュを有効にし、クエリヒントを使用して Gremlin 読み取り専用クエリの結果をキャッシュできます。

クエリを再実行すると、キャッシュ内に残っている限り、低レイテンシーで I/O コストなしでキャッシュされた結果を取得します。これは、HTTP エンドポイントと WebSocket を使用して、バイトコードまたは文字列形式で送信されたクエリに対して機能します。

**注記**  
プロファイルエンドポイントに送信されたクエリは、クエリキャッシュが有効になっていてもキャッシュされません。

Neptune クエリ結果キャッシュの動作は、いくつかの方法で制御できます。例えば、次のようになります。
+ キャッシュされた結果をブロック単位でページ分割できます。
+ 指定したクエリの有効期限 (TTL) を指定できます。
+ 指定したクエリのキャッシュをクリアすることができます。
+ キャッシュ全体をクリアできます。
+ 結果がキャッシュサイズを超えた場合に通知されるように設定できます。

キャッシュは、LRU (least-recently-used) ポリシーを使用して維持されます。つまり、キャッシュに割り当てられた領域がいっぱいになると、新しい結果がキャッシュされるときに参照される頻度が最も低い結果が削除され、スペースが確保されます。

**重要**  
クエリ結果キャッシュは、`t3.medium` または `t4.medium` インスタンスタイプでは使用できません。

## Neptune でクエリ結果キャッシュを有効にする
<a name="gremlin-results-cache-enabling"></a>

 クエリ結果のキャッシュは、クラスター内のすべてのインスタンスに対して、またはインスタンスごとに有効にできます。クラスター内のすべてのインスタンスで結果のキャッシュを有効にするには、クラスターの `cluster-parameter-group` の `neptune_result_cache` パラメータを `1` に設定します。特定のインスタンスでこれを有効にするには、インスタンスの `instance-parameter-group` の `neptune_result_cache` パラメータを `1` に設定します。クラスターパラメータグループ設定は、インスタンスパラメータグループ値を上書きします。

 結果のキャッシュパラメータ設定を適用するには、影響を受けるインスタンスで再起動が必要です。`cluster-parameter-group` を介してクラスター内のすべてのインスタンスで結果のキャッシュを有効にできますが、各インスタンスは独自のキャッシュを保持します。クエリ結果のキャッシュ機能は、クラスター全体のキャッシュではありません。

結果キャッシュを有効にすると、Neptune は現在のメモリの一部をクエリ結果をキャッシュするために確保します。使用しているインスタンスタイプが大きくなり、使用可能なメモリが多いほど、Neptune がキャッシュに割り当てるメモリが多くなります。

結果キャッシュメモリがいっぱいになると、Neptune は参照される頻度が最も低い (LRU) キャッシュされた結果を自動的に減らし、新しい結果のための場所を空けます。

結果キャッシュの現在のステータスを確認するには、[インスタンスのステータス](access-graph-status.md) コマンドを使います。

## ヒントを使用してクエリ結果をキャッシュする
<a name="gremlin-results-cache-using"></a>

クエリ結果キャッシュを有効にすると、クエリヒントを使用してクエリキャッシュを制御します。以下の例はすべて、同じクエリトラバーサルに適用されます。

```
g.V().has('genre','drama').in('likes')
```

### `enableResultCache`の使用
<a name="using-enableResultCache"></a>

クエリ結果キャッシュを有効にした状態で、Gremlin クエリの結果をキャッシュするには、次のように `enableResultCache` クエリヒントを使います。

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

Neptune はクエリ結果を返し、キャッシュします。後で、まったく同じクエリを再度発行することで、キャッシュされた結果にアクセスできます。

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

キャッシュされた結果を識別するキャッシュキーは、クエリ文字列そのものです。

```
g.V().has('genre','drama').in('likes')
```

### `enableResultCacheWithTTL`の使用
<a name="using-enableResultCacheWithTTL"></a>

クエリ結果をキャッシュする期間を指定するには、`enableResultCacheWithTTL` クエリヒントを使います。たとえば、次のクエリでは、クエリ結果が 120 秒後に期限切れになるよう指定しています。

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

ここでもキャッシュされた結果を識別するキャッシュキーは、ベースクエリ文字列そのものです。

```
g.V().has('genre','drama').in('likes')
```

また、`enableResultCache` クエリヒントでそのクエリ文字列を使用して、キャッシュされた結果にアクセスできます。

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

結果がキャッシュされてから 120 秒以上経過すると、そのクエリは新しい結果を返し、有効期限 (TTL)なしでキャッシュします。

キャッシュされた結果にアクセスするには、`enableResultCacheWithTTL` クエリヒントで同じクエリを発行します。例えば、次のようになります。

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

120 秒が経過するまで (つまり、現在有効になっている TTL)、`enableResultCacheWithTTL` クエリヒントを使うこの新しいクエリは、キャッシュされた結果を返します。120 秒後、新しい結果が返され、有効期限 (TTL) 140 秒でキャッシュされます。

**注記**  
クエリキーの結果が既にキャッシュされている場合は、`enableResultCacheWithTTL` とともに同じクエリキーは、新しい結果を生成せず、現在キャッシュされている結果の有効期限 (TTL)には影響しません。  
結果が `enableResultCache` を使って以前にキャッシュされていた場合、`enableResultCacheWithTTL` が新しい結果を生成し、指定した TTL 用にキャッシュする前に、まずキャッシュをクリアする必要があります。
結果が `enableResultCachewithTTL` を使って以前にキャッシュされていた場合、`enableResultCacheWithTTL` が新しい結果を生成し、指定した TTL 用にキャッシュする前に、まず前の TTL を期限切れとする必要があります。

### `invalidateResultCacheKey`の使用
<a name="using-invalidateResultCacheKey"></a>

`invalidateResultCacheKey` クエリヒントを使って特定のクエリのキャッシュされた結果をクリアできます。例えば、次のようになります。

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

このクエリは、クエリキー、`g.V().has('genre','drama').in('likes')`、のキャッシュをクリアし、そのクエリの新しい結果を返します。

また、`invalidateResultCacheKey` と `enableResultCache` または `enableResultCacheWithTTL` を組み合わせることもできます。たとえば、次のクエリは、現在のキャッシュされた結果をクリアし、新しい結果をキャッシュして返します。

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

### `invalidateResultCache`の使用
<a name="using-invalidateResultCache"></a>

`invalidateResultCache` クエリヒントを使ってクエリ結果キャッシュのすべてのキャッシュされた結果をクリアできます。例えば、次のようになります。

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

このクエリは、結果キャッシュ全体をクリアし、そのクエリの新しい結果を返します。

また、`invalidateResultCache` と `enableResultCache` または `enableResultCacheWithTTL` を組み合わせることもできます。たとえば、次のクエリは、結果キャッシュ全体をクリアし、このクエリの新しい結果をキャッシュして返します。

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

## キャッシュされたクエリ結果のページ割り
<a name="gremlin-results-cache-paginating"></a>

次のような多数の結果を既にキャッシュしているとします。

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

それから、次の範囲クエリを発行するとします。

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

Neptune は最初に完全なキャッシュキーを探します。つまり `g.V().has('genre','drama').in('likes').range(0,10)` です。そのキーが存在しない場合、Neptune は次に範囲のないクエリ文字列のキーがあるかどうかを調べます (すなわち`g.V().has('genre','drama').in('likes')`)。そのキーが見つかると、Neptune は範囲が指定しているように、キャッシュから最初の 10 個の結果を取得します。

**注記**  
末尾に範囲があるクエリの `invalidateResultCacheKey` クエリヒントを使うと、Neptune は、範囲とクエリと完全に一致するものが見つからない場合、範囲のないクエリのキャッシュをクリアします。

### `numResultsCached`と使用する`.iterate()`
<a name="gremlin-results-cache-paginating-numResultsCached"></a>

`numResultsCached` クエリヒントを使用すると、キャッシュされているすべての結果を返さずに結果キャッシュに入力できます。これは、多数の結果をページ分割したい場合に便利です。

`numResultsCached` クエリヒントは、`iterate()` で終わるクエリでのみ機能します。

たとえば、サンプルクエリの最初の 50 の結果をキャッシュする場合は、次のようにします。

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

この場合、キャッシュ内のクエリキーは次のようになります。`g.with("Neptune#numResultsCached", 50).V().has('genre','drama').in('likes')`。このクエリを使用して、キャッシュされた結果の最初の 10 個を取得できます。

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

また、次のように、クエリから次の 10 個の結果を取得できます。

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

忘れずに `numResultsCached` ヒントを含めます！これはクエリキーの不可欠な部分であるため、キャッシュされた結果にアクセスするには、これが存在していなければなりません。

**`numResultsCached` 使用時には、心に留めておくべきことがいくつかあります。**
+ **`numResultsCached` で入力する番号がクエリの最後に適用されます。**  これは、たとえば、次のクエリが実際に結果を `(1000, 1500)` 範囲内にキャッシュしていることを意味します。

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).iterate()
  ```
+ **`numResultsCached` で入力する番号はキャッシュする結果の最大数を指定します。**  これは、たとえば、次のクエリが実際に結果を `(1000, 2000)` 範囲内にキャッシュしていることを意味します。

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 100000)
   .V().range(1000, 2000).iterate()
  ```
+ **`.range().iterate()` で終わるクエリによってキャッシュされる結果には独自の範囲があります。**  たとえば、次のようなクエリを使用して結果をキャッシュするとします。

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).iterate()
  ```

  キャッシュから最初の 100 個の結果を取得するには、次のようなクエリを記述します。

  ```
  g.with("Neptune#enableResultCache", true)
   .with("Neptune#numResultsCached", 500)
   .V().range(1000, 2000).range(0, 100)
  ```

  この100の結果は、範囲 `(1000, 1100)` 内の基本クエリの結果と同等になります。

## キャッシュされた結果を検索するために使用されるクエリキャッシュキー
<a name="gremlin-results-cache-query-keys"></a>

クエリの結果がキャッシュされた後、後続のクエリは新しい結果を生成するのではなく、キャッシュからの*クエリキャッシュキー*検索結果と同じものになります。クエリのクエリキャッシュキーは、次のように評価されます。

1. `numResultsCached` 以外のキャッシュ関連のクエリヒントはすべて無視されます。

1. 最後の `iterate()` ステップは無視されます。

1. 残りのクエリは、バイトコード表現に従って順序付けられます。

結果の文字列は、既にキャッシュ内にあるクエリ結果のインデックスと照合され、クエリにキャッシュヒットがあるかどうかを判断します。

例えば、次のようなクエリがあるとします。

```
g.withSideEffect('Neptune#typePromotion', false).with("Neptune#enableResultCache", true)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes').iterate()
```

このクエリは、次のバイトコードバージョンとして保存されます。

```
g.withSideEffect('Neptune#typePromotion', false)
 .with("Neptune#numResultsCached", 50)
 .V().has('genre','drama').in('likes')
```

## 結果キャッシュに関連する例外
<a name="gremlin-results-cache-exceptions"></a>

キャッシュしようとしているクエリの結果が大きすぎてキャッシュメモリに収まらない場合は、以前にキャッシュされたものをすべて削除した後でも、Neptune は `QueryLimitExceededException` 障害を見つけます。結果は返されず、例外によって次のエラーメッセージが生成されます。

```
The result size is larger than the allocated cache,
      please refer to results cache best practices for options to rerun the query.
```

`noCacheExceptions` クエリヒントを使って、次のようにこのメッセージを抑制できます。

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