使用 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() 所生成的原始查询。

  • 转换的遍历。这 Neptune 过转换 TinkerPop 遍历 Neptune 逻辑查询计划表示形式。在许多情况下,整个 TinkerPop 遍历转换为两个 Neptune 步骤:一个执行整个查询(NeptuneGraphQueryStep) 和一个将 Neptune 查询引擎输出转换回来的 TinkerPop 遍历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 运算符的步骤时,将使用以下方式运行从该点开始的整个遍历。 TinkerPop 步骤,即使后续步骤确实有本地 Neptune 运算符。

这种情况的例外是调用 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 特定部分的说明。