Usando o Gremlin explain API em Neptune - Amazon Neptune

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Usando o Gremlin explain API em Neptune

O Amazon Neptune explain API Gremlin retorna o plano de consulta que seria executado se uma consulta especificada fosse executada. Como o na verdade API não executa a consulta, o plano é retornado quase instantaneamente.

Ela difere da etapa TinkerPop .explain () para poder relatar informações específicas do mecanismo Neptune.

Informações contidas em um relatório explain do Gremlin

Um relatório de explain contém as seguintes informações:

  • A string de consulta conforme solicitado.

  • O percurso original. Esse é o objeto TinkerPop Traversal produzido pela análise da string de consulta em etapas. TinkerPop É equivalente à consulta original produzida pela execução da consulta .explain() em relação ao TinkerPop TinkerGraph.

  • O percurso convertido. Essa é a Travessia de Netuno produzida pela conversão da Traversal na representação do plano de consulta lógica de TinkerPop Netuno. Em muitos casos, a TinkerPop travessia inteira é convertida em duas etapas do Neptune: uma que executa a consulta inteira () NeptuneGraphQueryStep e outra que converte a saída do mecanismo de consulta Neptune novamente em Traversers (). TinkerPop NeptuneTraverserConverterStep

  • O percurso otimizado. Essa é a versão otimizada do plano de consulta do Neptune depois que ele é executado por meio de uma série de otimizadores de redução de trabalho estático que reescrevem a consulta com base na análise estática e nas cardinalidades estimadas. Esses otimizadores executam coisas como reordenar operadores com base em contagens de intervalo, remover operadores desnecessários ou redundantes, reorganizar filtros, enviar operadores para grupos diferentes e assim por diante.

  • A contagem de predicados. Devido à estratégia de indexação do Neptune descrita anteriormente, ter um grande número de predicados diferentes pode ocasionar problemas de desempenho. Isso é especialmente verdadeiro para consultas que usam operadores de travessia reversa sem rótulo de borda (.in ou .both). Se esses operadores forem usados e a contagem de predicados for alta o suficiente, o relatório de explain exibirá uma mensagem de aviso.

  • DFEinformação. Quando o mecanismo DFE alternativo está ativado, os seguintes componentes de travessia podem aparecer na travessia otimizada:

    • DFEStep— Uma etapa DFE otimizada para Netuno na travessia que contém uma criança. DFENode DFESteprepresenta a parte do plano de consulta que é executada no DFE mecanismo.

    • DFENode: contém a representação intermediária como um ou mais DFEJoinGroupNodes secundários.

    • DFEJoinGroupNode: representa uma junção de um ou mais elementos DFENode ou DFEJoinGroupNode.

    • NeptuneInterleavingStep— Uma etapa DFE otimizada para Netuno na travessia que contém uma criança. DFEStep

      Também apresenta um elemento stepInfo que contém informações sobre o percurso, como o elemento de fronteira, os elementos do caminho usados, etc. Essas informações são usadas para processar a DFEStep secundária.

    Uma maneira fácil de descobrir se sua consulta está sendo avaliada por DFE é verificar se a explain saída contém umDFEStep. Qualquer parte da travessia que não faça parte do não DFEStep será executada DFE e será executada pelo TinkerPop motor.

    Consulte Exemplo com DFE ativado para obter um exemplo de relatório.

Sintaxe de explain do Gremlin

A sintaxe do explain API é a mesma da consulta for, exceto que ela é usada /gremlin/explain como endpoint em vez de/gremlin, como no exemplo a seguir. HTTP API

curl -X POST https://your-neptune-endpoint:port/gremlin/explain -d '{"gremlin":"g.V().limit(1)"}'

A consulta anterior produziria a saída a seguir.

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

Etapas não convertidas TinkerPop

Idealmente, todas as TinkerPop etapas de uma travessia têm cobertura nativa do operador Neptune. Quando esse não é o caso, o Neptune recorre à execução de etapas devido a lacunas TinkerPop na cobertura do operador. Se um percurso usar uma etapa para a qual o Neptune ainda não tem cobertura nativa, o relatório do explain exibirá um aviso mostrando onde ocorreu o déficit.

Quando uma etapa sem um operador de Netuno nativo correspondente é encontrada, toda a travessia daquele ponto em diante é executada TinkerPop usando etapas, mesmo que as etapas subsequentes tenham operadores nativos de Netuno.

A exceção ocorre ao invocar a pesquisa de texto completo do Neptune. O NeptuneSearchStep implementa etapas sem equivalentes nativos como etapas de pesquisa de texto completo.

Exemplo de saída de explain em que todas as etapas de uma consulta têm equivalentes nativos

Veja a seguir um exemplo de relatório explain de uma consulta em que todas as etapas têm equivalentes nativos:

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

Exemplo em que algumas etapas de uma consulta não têm equivalentes nativos

O Neptune lida com GraphStep e VertexStep de forma nativa, mas se você inserir uma FoldStep e uma UnfoldStep, a saída de explain resultante será diferente:

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

Nesse caso, a FoldStep interrompe a execução nativa. Mas até mesmo a VertexStep subsequente não é mais tratada nativamente porque ela aparece downstream das etapas de Fold/Unfold.

Para obter desempenho e economia de custos, é importante que você tente formular percursos para que a quantidade máxima de trabalho possível seja feita de forma nativa dentro do mecanismo de consulta Neptune, em vez de nas implementações por etapas. TinkerPop

Exemplo de uma consulta que usa Neptune full-text-search

A seguinte consulta usa a pesquisa de texto completo do 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*")

A parte .has("name", "Neptune#fts mark*") limita a pesquisa a vértices com name, enquanto .has("Person", "name", "Neptune#fts mark*") limita a pesquisa a vértices com name e o rótulo Person. Isso resulta no seguinte percurso no relatório 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} } }]

Exemplo de uso explain quando o DFE está ativado

Veja a seguir um exemplo de um explain relatório quando o mecanismo de consulta DFE alternativo está ativado:

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

Consulte Informações no explain para obter uma descrição das seções DFE específicas do relatório.