使用 GrelinexplainNeptune 中的 API - Amazon Neptune
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

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

使用 GrelinexplainNeptune 中的 API

亚 Amazon Neptune GrelinexplainAPI 返回将在运行指定查询时执行的查询计划。由于该 API 实际上并未运行查询,因此几乎可即时返回计划。

它与 TinkerPop .explain () 步骤不同,以便能够报告特定于 Neptune 引擎的信息。

Gremlin 中包含的信息explain报告

网络 ACL 和安全组都允许 (因此可到达您的实例) 的发起 ping 的explain报告包含以下信息:

  • 要求的查询字符串。

  • 原始遍历。这是通过将查询字符串解析为 TinkerPop 步骤而生成的 TinkerPop 遍历对象。它等同于针对 TinkerPop TinkerGraph 在查询上运行 .explain() 所生成的原始查询。

  • 转换的遍历。这是通过将 TinkerPop 遍历转换为 Neptune 逻辑查询计划表示形式而生成的 Neptune 遍历。在许多情况下,整个 TinkerPop 遍历都将转换为两个 Neptune 步骤:一个步骤执行整个查询 (NeptuneGraphQueryStep)和一个将 Neptune 查询引擎输出转换回 TinkerPop Traversers 的一个(NeptuneTraverserConverterStep)。

  • 优化的遍历。这是 Neptune 查询计划的优化版本运行一系列静态减负优化器以根据静态分析和估计基数来重写查询。优化器执行多种操作,例如根据范围计数对运算符进行重新排序、删除不必要或多余的运算符、重新排列筛选条件、将运算符推入不同的组等。

  • 谓词数量。由于前面所述的 Neptune 索引策略,具有大量不同谓词可能会导致性能问题。对于使用没有边缘标签(.in.both)的反向遍历运算符的查询,这一点尤为明显。如果使用了此类运算符并且谓词数量足够多,explain 报告将显示警告消息。

  • DFE 信息。启用 DFE 替代引擎后,优化的遍历中可能会显示以下遍历组件:

    • DFEStep— Neptune 优化了包含孩子的穿越过程中的 DFE 步骤DFENode.DFEStep表示在 DFE 引擎中执行的查询计划的一部分。

    • DFENode— 包含作为一个或多个子项的中间表示DFEJoinGroupNodes.

    • DFEJoinGroupNode— 表示一个或多个的连接DFENode要么DFEJoinGroupNode元素。

    • NeptuneInterleavingStep— Neptune 优化了包含孩子的穿越过程中的 DFE 步骤DFEStep.

      还包含stepInfo元素,其中包含有关遍历的信息,例如前沿元素、使用的路径元素等。这些信息用于处理孩子DFEStep.

    了解 DFE 是否正在评估查询的一种简单方法是检查是否explain输出包含DFEStep. 穿越的任何部分不属于DFEStep将不会由 DFE 执行,将由 TinkerPop 引擎执行。

    请参阅启用 DFE 的示例以获取示例报告。

Gremlinexplain句法

explain API 的语法与查询的 HTTP API 相同,不同之处在于,它使用 /gremlin/explain 作为终端节点而不是 /gremlin,如以下示例所示。

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 将使遍历跳出本机执行。同时,后续的 VertexStep 也不再在本机处理,因为它出现在 Fold/Unfold 步骤之后。

出于性能和成本考虑,请在编制遍历时让尽可能多的工作在 Neptune 查询引擎内部进行,而不是通过 TinkerPop 步骤实现处理。

使用 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} } }]

使用的示例explain启用 DFE 时

以下是示例:explain报告何时启用 DFE 替代查询引擎:

******************************************************* 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

请参阅中的 信息explain有关报告中 DFE 特定部分的描述。