本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用 Grelinexplain
Neptune 中的 API
Amazon Neptune Grelinexplain
API 返回将在运行指定查询时执行的查询计划。由于该 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 处理两者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 全文搜索的查询示例
以下查询使用 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 特定部分的说明。