

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

# Neptune での Gremlin `explain` APIの使用
<a name="gremlin-explain-api"></a>

Amazon Neptune Gremlin `explain` API は、指定されたクエリが実行された場合に実行されるクエリプランを返します。API はクエリを実際に実行しないため、プランはほぼ瞬時に返されます。

Neptune エンジンに固有の情報をレポートできるため、TinkerPop .explain() ステップとは異なります。

## Gremlin `explain` レポートに含まれる情報
<a name="gremlin-explain-api-results"></a>

`explain` レポートには、以下の情報が含まれています。
+ リクエストされたクエリ文字列。
+ **元のトラバーサル。**これは、クエリ文字列を TinkerPop ステップに解析して生成される TinkerPop Traversal オブジェクトです。これは元のクエリと同等で、TinkerPop TinkerGraph に対してクエリで `.explain()` を実行することによって生成されます。
+ **変換されたトラバーサル。**これは、TinkerPop Traversal を Neptune 論理クエリプラン表現に変換することによって生成される Neptune トラバーサルです。多くの場合、TinkerPop トラバーサル全体が 2 つの Neptune ステップに変換されます。1 つはクエリ全体を実行するステップ (`NeptuneGraphQueryStep`) で、もう 1 つは Neptune クエリエンジン出力を TinkerPop トラバーサーに変換し直しすステップ (`NeptuneTraverserConverterStep`) です。
+ **最適化されたトラバーサル。**これは、静的分析と推定基数に基づいてクエリを書き換える一連の静的作業削減オプティマイザを実行した後の Neptune クエリプランの最適化バージョンです。これらのオプティマイザは、範囲カウントに基づく演算子の順序変更、不要または冗長な演算子の除外、フィルタの再配置、異なるグループへの演算子のプッシュなどを行います。
+ **述語のカウント。**前述の Neptune インデックス作成戦略のため、多数の異なる述語があると、パフォーマンスの問題が発生する可能性があります。これは、エッジラベル (`.in` または `.both`) のないリバーストラバーサル演算子を使用するクエリに特に当てはまります。このような演算子が使用され、述語数が十分に高い場合、`explain` レポートには警告メッセージが表示されます。
+ **DFE 情報** DFE 代替エンジンが有効な場合、最適化トラバーサルに次のトラバーサルコンポーネントが表示されることがあります。
  + **`DFEStep`**   –   子 `DFENode` を含むトラバーサルの Neptune 最適化 DFE ステップ。`DFEStep` は、DFE エンジンで実行されるクエリプランの一部を表します。
  + **`DFENode`**   –   中間表現を 1 つ以上の子 `DFEJoinGroupNodes` として含みます。
  + **`DFEJoinGroupNode`**   –   1 つ以上の `DFENode` または `DFEJoinGroupNode` 要素の結合を表します。
  + **`NeptuneInterleavingStep`**   –  子 `DFEStep` を含むトラバーサルの Neptune 最適化 DFE ステップ。

    また、フロンティア要素、使用されるパス要素など、トラバーサルに関する情報を含む `stepInfo` 要素を含みます。この情報は、子 `DFEStep` の処理に使用されます。

  クエリが DFE によって評価されているかどうかを簡単に調べるには、`explain` 出力に `DFEStep` が含まれるかを確認します。`DFEStep` の一部ではない任意のトラバーサル部分は DFE によって実行されず、TinkerPop エンジンによって実行されます。

  サンプルレポートに関しては [DFE が有効な場合の例](#gremlin-explain-dfe) を参照してください。

## Gremlin `explain` 構文
<a name="gremlin-explain-api-syntax"></a>

`explain` API の構文は、クエリ用の HTTP API の構文と同じですが、次の例のように`/gremlin`、 ではなくエンドポイント`/gremlin/explain`として を使用する点が異なります。

------
#### [ AWS CLI ]

```
aws neptunedata execute-gremlin-explain-query \
  --endpoint-url https://{{your-neptune-endpoint}}:{{port}} \
  --gremlin-query "g.V().limit(1)"
```

詳細については、 AWS CLI 「 コマンドリファレンス」の[execute-gremlin-explain-query](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/execute-gremlin-explain-query.html)」を参照してください。

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://{{your-neptune-endpoint}}:{{port}}',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.execute_gremlin_explain_query(
    gremlinQuery='g.V().limit(1)'
)

print(response['output'])
```

Java、.NET などの他の言語の AWS SDK の例については、「」を参照してください[AWS SDK](access-graph-gremlin-sdk.md)。

------
#### [ awscurl ]

```
awscurl https://{{your-neptune-endpoint}}:{{port}}/gremlin/explain \
  --region {{us-east-1}} \
  --service neptune-db \
  -X POST \
  -d '{"gremlin":"g.V().limit(1)"}'
```

**注記**  
この例では、 AWS 認証情報が 環境で設定されていることを前提としています。{{us-east-1}} を Neptune クラスターのリージョンに置き換えます。

IAM 認証**awscurl**で を使用する方法の詳細については、「」を参照してください[一時的な認証情報で `awscurl` を使用して、IAM 認証が有効になっている DB クラスターに安全に接続する](iam-auth-connect-command-line.md#iam-auth-connect-awscurl)。

------
#### [ curl ]

```
curl -X POST https://{{your-neptune-endpoint}}:{{port}}/gremlin/explain \
  -d '{"gremlin":"g.V().limit(1)"}'
```

------

前述のクエリでは、次の出力が生成されます。

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============
g.V().limit(1)

Original Traversal
==================
[GraphStep(vertex,[]), RangeGlobalStep(0,1)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
        }, finishers=[limit(1)], annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .], {estimatedCardinality=INFINITY}
        }, finishers=[limit(1)], annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 18
```

## 未変換の TinkerPop ステップ
<a name="gremlin-explain-unconverted-steps"></a>

理想的には、トラバーサルのすべての TinkerPop ステップにネイティブ Neptune 演算子カバレッジがあります。これに当てはまらない場合、Neptune は TinkerPop ステップの実行をフォールバックして、演算子カバレッジのギャップを確認します。Neptune がネイティブカバレッジを持っていないステップをトラバーサルで使用している場合、`explain` レポートにはギャップが発生した場所を示す警告が表示されます。

対応するネイティブ Neptune 演算子がないステップが検出されると、後続のステップにネイティブ Neptune 演算子がある場合でも、その時点からのトラバーサル全体が TinkerPop ステップを使用して実行されます。

ただし、Neptune フルテキスト検索が呼び出される場合は例外です。NeptuneSearchStep は、フルテキスト検索ステップとして同等のネイティブがないステップを実装します。

## クエリのすべてのステップに同等のネイティブがある `explain` 出力例
<a name="gremlin-explain-all-steps-converted"></a>

以下に、すべてのステップに同等のネイティブがあるクエリの `explain` レポートの例を示します。

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============
g.V().out()

Original Traversal
==================
[GraphStep(vertex,[]), VertexStep(OUT,vertex)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
            PatternNode[(?1, ?5, ?3, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .]
            PatternNode[(?3, <~label>, ?4, <~>) . project ask .]
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep], maxVarId=7}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, ?5, ?3, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=INFINITY}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep], maxVarId=7}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 18
```

## クエリ内の一部のステップに同等のネイティブがない例
<a name="gremlin-explain-not-all-steps-converted"></a>

Neptune は `GraphStep` と `VertexStep` の両方をネイティブに処理しますが、`FoldStep` と `UnfoldStep` を導入すると、結果 `explain` 出力は異なります。

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============
g.V().fold().unfold().out()

Original Traversal
==================
[GraphStep(vertex,[]), FoldStep, UnfoldStep, VertexStep(OUT,vertex)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
        }, annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep
]
+ not converted into Neptune steps: [FoldStep, UnfoldStep, VertexStep(OUT,vertex)]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(Vertex) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .], {estimatedCardinality=INFINITY}
        }, annotations={path=[Vertex(?1):GraphStep], maxVarId=3}
    },
    NeptuneTraverserConverterStep,
    NeptuneMemoryTrackerStep
]
+ not converted into Neptune steps: [FoldStep, UnfoldStep, VertexStep(OUT,vertex)]

WARNING: >> FoldStep << is not supported natively yet
```

この場合、`FoldStep` はネイティブ実行を中断します。ただし、`Fold/Unfold` ステップの下流に表示されるため、後続の `VertexStep` もネイティブに処理されなくなります。

パフォーマンスとコスト削減のためには、TinkerPop ステップ実装ではなく、可能な最大量の作業が Neptune クエリエンジン内でネイティブに行われるように、トラバーサルを策定することが重要です。

## Neptune フルテキスト検索を使用するクエリの例
<a name="gremlin-explain-full-text-search-steps"></a>

次のクエリでは、Neptune フルテキスト検索を使用します。

```
g.withSideEffect("{{Neptune#fts.endpoint}}", "{{some_endpoint}}")
  .V()
  .tail(100)
  .has("Neptune#fts mark*")
  -------
  .has("name", "Neptune#fts mark*")
  .has("Person", "name", "Neptune#fts mark*")
```

`.has("name", "Neptune#fts mark*")` パートは、検索の対象を `name` を持つ頂点に制限します。`.has("Person", "name", "Neptune#fts mark*")` は、検索の対象を `name` およびラベル `Person` を持つ頂点に制限します。これにより、`explain` レポートのトラバーサルは次のようになります。

```
Final Traversal
[NeptuneGraphQueryStep(Vertex) {
    JoinGroupNode {
        PatternNode[(?1, termid(1,URI), ?2, termid(0,URI)) . project distinct ?1 .], {estimatedCardinality=INFINITY}
    }, annotations={path=[Vertex(?1):GraphStep], maxVarId=4}
}, NeptuneTraverserConverterStep, NeptuneTailGlobalStep(10), NeptuneTinkerpopTraverserConverterStep, NeptuneSearchStep {
    JoinGroupNode {
        SearchNode[(idVar=?3, query=mark*, field=name) . project ask .], {endpoint=some_endpoint}
    }
    JoinGroupNode {
        SearchNode[(idVar=?3, query=mark*, field=name) . project ask .], {endpoint=some_endpoint}
    }
}]
```

## DFE が有効な場合の `explain` 使用例
<a name="gremlin-explain-dfe"></a>

DFE 代替クエリエンジンが有効な場合の `explain` レポート例を次に示します。

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============

g.V().as("a").out().has("name", "josh").out().in().where(eq("a"))


Original Traversal
==================
[GraphStep(vertex,[])@[a], VertexStep(OUT,vertex), HasStep([name.eq(josh)]), VertexStep(OUT,vertex), VertexStep(IN,vertex), WherePredicateStep(eq(a))]

Converted Traversal
===================
Neptune steps:
[
    DFEStep(Vertex) {
      DFENode {
        DFEJoinGroupNode[ children={
          DFEPatternNode[(?1, <http://www.w3.org/1999/02/22-rdf-syntax-ns#type>, ?2, <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph>) . project DISTINCT[?1] {rangeCountEstimate=unknown}],
          DFEPatternNode[(?1, ?3, ?4, ?5) . project ALL[?1, ?4] graphFilters=(!= <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph> . ), {rangeCountEstimate=unknown}]
        }, {rangeCountEstimate=unknown}
        ]
      } [Vertex(?1):GraphStep@[a], Vertex(?4):VertexStep]
    } ,
    NeptuneTraverserConverterDFEStep
]
+ not converted into Neptune steps: HasStep([name.eq(josh)]),
Neptune steps:
[
    NeptuneInterleavingStep {
      StepInfo[joinVars=[?7, ?1], frontierElement=Vertex(?7):HasStep, pathElements={a=(last,Vertex(?1):GraphStep@[a])}, listPathElement={}, indexTime=0ms],
      DFEStep(Vertex) {
        DFENode {
          DFEJoinGroupNode[ children={
            DFEPatternNode[(?7, ?8, ?9, ?10) . project ALL[?7, ?9] graphFilters=(!= <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph> . ), {rangeCountEstimate=unknown}],
            DFEPatternNode[(?12, ?11, ?9, ?13) . project ALL[?9, ?12] graphFilters=(!= <http://aws.amazon.com/neptune/vocab/v01/DefaultNamedGraph> . ), {rangeCountEstimate=unknown}]
          }, {rangeCountEstimate=unknown}
          ]
        } [Vertex(?9):VertexStep, Vertex(?12):VertexStep]
      } 
    }
]
+ not converted into Neptune steps: WherePredicateStep(eq(a)),
Neptune steps:
[
    DFECleanupStep
]


Optimized Traversal
===================
Neptune steps:
[
    DFEStep(Vertex) {
      DFENode {
        DFEJoinGroupNode[ children={
          DFEPatternNode[(?1, ?3, ?4, ?5) . project ALL[?1, ?4] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807}]
        }, {rangeCountEstimate=unknown}
        ]
      } [Vertex(?1):GraphStep@[a], Vertex(?4):VertexStep]
    } ,
    NeptuneTraverserConverterDFEStep
]
+ not converted into Neptune steps: NeptuneHasStep([name.eq(josh)]),
Neptune steps:
[
    NeptuneMemoryTrackerStep,
    NeptuneInterleavingStep {
      StepInfo[joinVars=[?7, ?1], frontierElement=Vertex(?7):HasStep, pathElements={a=(last,Vertex(?1):GraphStep@[a])}, listPathElement={}, indexTime=0ms],
      DFEStep(Vertex) {
        DFENode {
          DFEJoinGroupNode[ children={
            DFEPatternNode[(?7, ?8, ?9, ?10) . project ALL[?7, ?9] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807}],
            DFEPatternNode[(?12, ?11, ?9, ?13) . project ALL[?9, ?12] graphFilters=(!= defaultGraph[526] . ), {rangeCountEstimate=9223372036854775807}]
          }, {rangeCountEstimate=unknown}
          ]
        } [Vertex(?9):VertexStep, Vertex(?12):VertexStep]
      } 
    }
]
+ not converted into Neptune steps: WherePredicateStep(eq(a)),
Neptune steps:
[
    DFECleanupStep
]


WARNING: >> [NeptuneHasStep([name.eq(josh)]), WherePredicateStep(eq(a))] << (or one of the children for each step) is not supported natively yet

Predicates
==========
# of predicates: 8
```

レポート内の DFE 固有のセクションの詳細については、[`explain` 内の情報](#gremlin-explain-api-results) を参照してください。