Neptune での Gremlin explain APIの使用 - Amazon Neptune

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

Neptune での Gremlin explain APIの使用

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

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

Gremlin explain レポートに含まれる情報

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 構文

explain API の構文は、次の例のように、/gremlin/explain/gremlin の代わりにエンドポイントとして使用すること以外はクエリの HTTP API の構文と同じです。

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 ステップ

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

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

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

クエリのすべてのステップに同等のネイティブがある explain 出力例

以下に、すべてのステップに同等のネイティブがあるクエリの 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

クエリ内の一部のステップに同等のネイティブがない例

Neptune は GraphStepVertexStep の両方をネイティブに処理しますが、FoldStepUnfoldStep を導入すると、結果 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 フルテキスト検索を使用するクエリの例

次のクエリでは、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 使用例

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 内の情報 を参照してください。