

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Uso de la API `explain` de Gremlin en Neptune
<a name="gremlin-explain-api"></a>

La API de `explain` de Gremlin de Amazon Neptune devuelve el plan de consulta que se ejecutaría si se realizara una consulta especificada. Puesto que la API no ejecuta realmente la consulta, el plan se devuelve casi instantáneamente.

Se diferencia del paso TinkerPop .explain () para poder reportar información específica del motor de Neptune.

## Información contenida en un informe `explain` de Gremlin
<a name="gremlin-explain-api-results"></a>

Un informe `explain` contiene la siguiente información:
+ La cadena de consulta según se solicita.
+ **El recorrido original.** Este es el objeto TinkerPop Traversal que se produce al analizar la cadena de consulta en pasos. TinkerPop Es equivalente a la consulta original producida al ejecutar `.explain()` la consulta contra el. TinkerPop TinkerGraph
+ **El recorrido convertido.** Este es el recorrido de Neptuno producido al convertir el TinkerPop recorrido en la representación del plan de consulta lógico de Neptuno. En muchos casos, todo el TinkerPop recorrido se convierte en dos pasos de Neptuno: uno que ejecuta toda la consulta `NeptuneGraphQueryStep` () y otro que convierte la salida del motor de consultas de Neptuno en Traversers (). TinkerPop `NeptuneTraverserConverterStep`
+ **El recorrido optimizado.** Esta es la versión optimizada del plan de consultas de Neptune después de que se haya ejecutado a través de una serie de optimizadores estáticos de reducción de trabajo que reescriben la consulta en función del análisis estático y las cardinalidades estimadas. Esos optimizadores realizan tareas como reordenar operadores en función del recuento de rangos, eliminar operadores innecesarios o redundantes, reorganizar filtros, insertar operadores en diferentes grupos, etc.
+ **El recuento de predicados.** Debido a la estrategia de indexación de Neptune descrita anteriormente, disponer de un gran número de predicados diferentes puede provocar problemas de rendimiento. Esto es especialmente cierto para las consultas que utilizan operadores de recorrido inverso sin etiqueta de borde (`.in` o `.both`). Si se utilizan estos operadores y el recuento de predicados es lo suficientemente alto, el informe `explain` muestra un mensaje de advertencia.
+ **Información de DFE** Cuando el motor alternativo de DFE está habilitado, es posible que los siguientes componentes de recorrido aparezcan en el recorrido optimizado:
  + **`DFEStep`**: un paso de DFE optimizado para Neptune en el recorrido que contiene un `DFENode`secundario. `DFEStep` representa la parte del plan de consultas que se ejecuta en el motor DFE.
  + **`DFENode`**: contiene la representación intermedia como uno o más `DFEJoinGroupNodes` secundarios.
  + **`DFEJoinGroupNode`**: representa una unión de uno o más elementos `DFENode` o `DFEJoinGroupNode`.
  + **`NeptuneInterleavingStep`**: un paso de DFE optimizado para Neptune en el recorrido que contiene un `DFEStep`secundario.

    También contiene un elemento `stepInfo` que contiene información sobre el recorrido, como el elemento fronterizo, los elementos de la ruta utilizados, etc. Esta información se usa para procesar el `DFEStep` secundario.

  Una forma sencilla de averiguar si el DFE está evaluando su consulta consiste en comprobar si el resultado de `explain` contiene un `DFEStep`. Cualquier parte del recorrido que no forme parte del recorrido no será ejecutada por el DFE y `DFEStep` será ejecutada por el motor. TinkerPop 

  Consulte [Ejemplo con DFE habilitado](#gremlin-explain-dfe) para ver un informe de ejemplo.

## Sintaxis de `explain` de Gremlin
<a name="gremlin-explain-api-syntax"></a>

La sintaxis de la `explain` API es la misma que la de la API HTTP para consultas, excepto que se utiliza `/gremlin/explain` como punto final en lugar de hacerlo`/gremlin`, como en los ejemplos siguientes.

------
#### [ AWS CLI ]

```
aws neptunedata execute-gremlin-explain-query \
  --endpoint-url https://your-neptune-endpoint:port \
  --gremlin-query "g.V().limit(1)"
```

Para obtener más información, consulta [execute-gremlin-explain-query](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/execute-gremlin-explain-query.html)la Referencia de AWS CLI comandos.

------
#### [ SDK ]

```
import boto3
from botocore.config import Config

client = boto3.client(
    'neptunedata',
    endpoint_url='https://your-neptune-endpoint:port',
    config=Config(read_timeout=None, retries={'total_max_attempts': 1})
)

response = client.execute_gremlin_explain_query(
    gremlinQuery='g.V().limit(1)'
)

print(response['output'])
```

Para ver ejemplos de AWS SDK en otros lenguajes, como Java, .NET y más, consulte[AWS SDK](access-graph-gremlin-sdk.md).

------
#### [ awscurl ]

```
awscurl https://your-neptune-endpoint:port/gremlin/explain \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -d '{"gremlin":"g.V().limit(1)"}'
```

**nota**  
En este ejemplo se supone que sus AWS credenciales están configuradas en su entorno. *us-east-1*Sustitúyala por la región de tu cúmulo de Neptuno.

Para obtener más información sobre el uso **awscurl** con la autenticación de IAM, consulte. [Uso de `awscurl` con credenciales temporales para conectarse de forma segura a un clúster de base de datos con la autenticación de IAM habilitada](iam-auth-connect-command-line.md#iam-auth-connect-awscurl)

------
#### [ curl ]

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

------

La consulta anterior produciría el siguiente resultado.

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

## Pasos no convertidos TinkerPop
<a name="gremlin-explain-unconverted-steps"></a>

Lo ideal es que todos los TinkerPop pasos de un recorrido cuenten con la cobertura nativa del operador de Neptune. Cuando este no es el caso, Neptune recurre a la ejecución TinkerPop escalonada para cubrir las brechas en la cobertura de sus operadores. Si un recorrido utiliza un paso para el que Neptune todavía no tiene cobertura nativa, el informe `explain` muestra una advertencia que indica dónde se produjo la brecha.

Cuando se encuentra un paso sin un operador nativo de Neptuno correspondiente, todo el recorrido desde ese punto en adelante se ejecuta mediante TinkerPop pasos, incluso si los pasos posteriores tienen operadores nativos de Neptuno.

La excepción a esto se produce cuando se invoca la búsqueda de texto completo de Neptune. NeptuneSearchStep Implementa los pasos sin equivalentes nativos como pasos de búsqueda de texto completo.

## Ejemplo de resultado de `explain` donde todos los pasos de una consulta tienen equivalentes nativos
<a name="gremlin-explain-all-steps-converted"></a>

A continuación se muestra un ejemplo de informe `explain` para una consulta en la que todos los pasos tienen 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
```

## Ejemplo en el que algunos pasos de una consulta no tienen equivalentes nativos
<a name="gremlin-explain-not-all-steps-converted"></a>

Neptune gestiona `GraphStep` y `VertexStep` de forma nativa, pero si introduce un `FoldStep` y `UnfoldStep`, el `explain` resultante es 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
```

En este caso, `FoldStep` elimina la ejecución nativa. Sin embargo, incluso el `VertexStep` siguiente ya no se gestiona de forma nativa, ya que aparece después de los pasos `Fold/Unfold`.

Para ahorrar rendimiento y costes, es importante que intente formular los recorridos de forma que la mayor cantidad de trabajo posible se realice de forma nativa dentro del motor de consultas de Neptune, en lugar de hacerlo paso a paso. TinkerPop 

## Ejemplo de consulta que usa Neptune full-text-search
<a name="gremlin-explain-full-text-search-steps"></a>

En la siguiente consulta se utiliza la búsqueda de texto completo de 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*")
```

La parte `.has("name", "Neptune#fts mark*")` limita la búsqueda a los vértices con `name`, mientras que `.has("Person", "name", "Neptune#fts mark*")` limita la búsqueda a los vértices con `name` y la etiqueta `Person`. Esto da como resultado el siguiente recorrido en el informe `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}
    }
}]
```

## Ejemplo de uso de `explain` cuando DFE está habilitado
<a name="gremlin-explain-dfe"></a>

El siguiente es un ejemplo de un informe `explain` cuando el motor de consultas alternativo DFE está habilitado:

```
*******************************************************
                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 [Información en `explain`](#gremlin-explain-api-results) para obtener una descripción de las secciones específicas de DFE en el informe.