本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
在 Neptune 中使用小精灵 explain
API
Amazon Neptune Gremlin explain
API 返回运行指定查询时将执行的查询计划。由于实际上API并未运行查询,因此计划几乎是即时返回的。
它与 TinkerPop .explain () 步骤的不同之处在于能够报告特定于 Neptune 引擎的信息。
Gremlin explain
报告中包含的信息
explain
报告包含以下信息:
要求的查询字符串。
原始遍历。这是通过将查询字符串解析为步骤而生成的 TinkerPop Traversal 对象。 TinkerPop 它等同于在针对的查询
.explain()
上运行所产生的原始查询 TinkerPop TinkerGraph。转换的遍历。这是通过将遍历转换为海王星逻辑查询计划表示形式而生成的 Neptune Trav TinkerPop ersal。在许多情况下,整个 TinkerPop 遍历会转换为两个 Neptune 步骤:一个执行整个查询 (
NeptuneGraphQueryStep
),另一个将海王星查询引擎的输出转换回 Traversers ()。 TinkerPopNeptuneTraverserConverterStep
优化的遍历。这是 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启用的示例。
-
Gremlin explain
语法
的语法与 for 查询HTTPAPI的语法相同,唯一的不同explain
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 原生处理 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
将使遍历跳出本机执行。同时,后续的 VertexStep
也不再在本机处理,因为它出现在 Fold/Unfold
步骤之后。
为了提高性能和节省成本,请务必尝试制定遍历公式,以便在 Neptune 查询引擎中以本机方式完成尽可能多的工作,而不是通过分步实现。 TinkerPop
使用 Neptune 的查询示例 full-text-search
以下查询使用 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
以下是启用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
explain 中的信息有关报告中DFE特定部分的说明,请参阅。