Amazon Neptune Gremlin でクエリ結果をキャッシュする - Amazon Neptune

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

Amazon Neptune Gremlin でクエリ結果をキャッシュする

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

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

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

注記

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

Neptune クエリ結果キャッシュの動作は、いくつかの方法で制御できます。例:

  • キャッシュされた結果をブロック単位でページ分割できます。

  • 指定されたクエリの time-to-live (TTL) を指定できます。

  • 指定したクエリのキャッシュをクリアすることができます。

  • キャッシュ全体をクリアできます。

  • 結果がキャッシュサイズを超えた場合に通知されるように設定できます。

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

重要

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

Neptune でクエリ結果キャッシュを有効にする

Neptune でクエリ結果キャッシュを有効にするには、コンソールを使用して neptune_result_cache DB インスタンスのパラメータを 1 (有効に) 設定します。

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

結果のキャッシュメモリがいっぱいになると、Neptune は least-recently-used (LRU) キャッシュされた結果を自動的に削除して、新しい結果に取り掛かります。

結果キャッシュの現在のステータスを確認するには、インスタンスのステータス コマンドを使います。

ヒントを使用してクエリ結果をキャッシュする

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

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

enableResultCache を使用する

クエリ結果キャッシュを有効にした状態で、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 を使用する

クエリ結果をキャッシュする期間を指定するには、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 秒以上経過した場合、そのクエリは新しい結果を返し、 なしでキャッシュします time-to-live。

キャッシュされた結果にアクセスするには、enableResultCacheWithTTL クエリヒントで同じクエリを発行します。例:

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

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

注記

クエリキーの結果がすでにキャッシュされている場合、 と同じクエリキーenableResultCacheWithTTLは新しい結果を生成せず、現在キャッシュされている結果 time-to-live の には影響しません。

  • 結果が enableResultCache を使って以前にキャッシュされていた場合、enableResultCacheWithTTL が新しい結果を生成し、指定した TTL 用にキャッシュする前に、まずキャッシュをクリアする必要があります。

  • 結果が enableResultCachewithTTL を使って以前にキャッシュされていた場合、enableResultCacheWithTTL が新しい結果を生成し、指定した TTL 用にキャッシュする前に、まず前の TTL を期限切れとする必要があります。

invalidateResultCacheKey を使用する

invalidateResultCacheKey クエリヒントを使って特定のクエリのキャッシュされた結果をクリアできます。例:

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

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

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

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

invalidateResultCache を使用する

invalidateResultCache クエリヒントを使ってクエリ結果キャッシュのすべてのキャッシュされた結果をクリアできます。例:

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

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

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

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

キャッシュされたクエリ結果のページ割り

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

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()

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) 内の基本クエリの結果と同等になります。

キャッシュされた結果を検索するために使用されるクエリキャッシュキー

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

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

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

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

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

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

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')

結果キャッシュに関連する例外

キャッシュしようとしているクエリの結果が大きすぎてキャッシュメモリに収まらない場合は、以前にキャッシュされたものをすべて削除した後でも、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')