

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.

# La característica `explain` de openCypher
<a name="access-graph-opencypher-explain"></a>

La característica `explain` de openCypher es una herramienta de autoservicio de Amazon Neptune que le ayuda a entender el enfoque de ejecución adoptado por el motor de Neptune. Para invocar a explain, se pasa un parámetro a una solicitud [HTTPS](access-graph-opencypher-queries.md) de openCypher con`explain=mode`, donde el valor de `mode` puede ser uno de los siguientes:

****
+ **`static`**: en el modo `static`, `explain` solo imprime la estructura estática del plan de consulta. En realidad, no ejecuta la consulta.
+ **`dynamic`**: en el modo `dynamic`, `explain` también ejecuta la consulta e incluye los aspectos dinámicos del plan de consulta. Estos ellos, se puede incluir el número de enlaces intermedios que fluyen a través de los operadores, la proporción entre los enlaces entrantes y los enlaces salientes y el tiempo total que necesita cada operador.
+ **`details`**: en el modo de `details`, `explain` imprime la información mostrada en el modo dinámico más detalles adicionales como la cadena de consulta de openCypher real y el recuento de intervalo estimado para el patrón subyacente de un operador de unión.

  

Por ejemplo, usando el modo `POST` with`dynamic`:

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

```
aws neptunedata execute-open-cypher-explain-query \
  --endpoint-url https://your-neptune-endpoint:port \
  --open-cypher-query "MATCH (n) RETURN n LIMIT 1" \
  --explain-mode dynamic
```

Para obtener más información, consulte [execute-open-cypher-explain-query](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/execute-open-cypher-explain-query.html) en 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_open_cypher_explain_query(
    openCypherQuery='MATCH (n) RETURN n LIMIT 1',
    explainMode='dynamic'
)

print(response['results'].read().decode('utf-8'))
```

Para ver ejemplos de AWS SDK en otros idiomas, consulte[AWS SDK](access-graph-opencypher-sdk.md).

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

```
awscurl https://your-neptune-endpoint:port/openCypher \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -d "query=MATCH (n) RETURN n LIMIT 1" \
  -d "explain=dynamic"
```

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

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

```
curl https://your-neptune-endpoint:port/openCypher \
  -d "query=MATCH (n) RETURN n LIMIT 1" \
  -d "explain=dynamic"
```

------

## Limitaciones de `explain` de openCypher en Neptune
<a name="access-graph-opencypher-explain-limitations"></a>

La versión actual de explain de openCypher tiene las siguientes limitaciones:
+ Actualmente, los planes de explain solo están disponibles para consultas que realizan operaciones de solo lectura. No se admiten consultas que realicen algún tipo de mutación, como `CREATE`, `DELETE`, `MERGE`, `SET`, etc.
+ Los operadores y la salida de un plan específico pueden cambiar en futuras versiones.

## Operadores de DFE en la salida de `explain` de openCypher
<a name="access-graph-opencypher-dfe-operators"></a>

Para utilizar la información que proporciona la característica `explain` de openCypher, debe comprender algunos detalles sobre el funcionamiento del [motor de consultas DFE](neptune-dfe-engine.md) (DFE es el motor que utiliza Neptune para procesar las consultas de openCypher).

El motor DFE traduce cada consulta en una canalización de operadores. Partiendo del primer operador, las soluciones intermedias fluyen de un operador al siguiente a través de esta canalización de operadores. Cada fila de la tabla explain representa un resultado, hasta el punto de evaluación.

Los operadores que pueden aparecer en un plan de consulta de DFE son los siguientes:

**DFEApply**— Ejecuta la función especificada en la sección de argumentos, sobre el valor almacenado en la variable especificada

**DFEBindRelación**: une variables con los nombres especificados

**DFEChunkLocalSubQuery**— Se trata de una operación sin bloqueo que actúa como un contenedor alrededor de las subconsultas que se están realizando.

**DFEDistinctColumna**: devuelve el subconjunto distinto de los valores de entrada en función de la variable especificada.

**DFEDistinctRelación**: devuelve el subconjunto distinto de las soluciones de entrada en función de la variable especificada.

**DFEDrain**— Aparece al final de una subconsulta para actuar como paso de finalización de esa subconsulta. El número de soluciones se registra como `Units In`. `Units Out` siempre es cero.

**DFEForwardValor**: copia todos los fragmentos de entrada directamente como fragmentos de salida para pasarlos a su operador descendente.

**DFEGroupByHashIndex**— Realiza una operación de agrupamiento sobre las soluciones de entrada en función de un índice hash previamente calculado (mediante la operación). `DFEHashIndexBuild` Como salida, la entrada especificada se amplía con una columna que contiene una clave de grupo para cada solución de entrada.

**DFEHashIndexBuild**— Crea un índice hash sobre un conjunto de variables como efecto secundario. Este índice hash se suele reutilizar en operaciones posteriores. Consulte `DFEHashIndexJoin` o `DFEGroupByHashIndex` para ver dónde podría usarse este índice hash.

**DFEHashIndexJoin**— Realiza una combinación de las soluciones entrantes con un índice hash creado previamente. Consulte `DFEHashIndexBuild` para ver dónde podría crear este índice hash.

**DFEJoinExiste**: toma una relación de entrada izquierda y derecha y conserva los valores de la relación izquierda que tienen un valor correspondiente en la relación derecha, tal como se define en las variables de unión dadas. 

****: se trata de una operación sin bloqueo que actúa como encapsulador de una subconsulta, lo que permite que se ejecute repetidamente para su uso en bucles.

**DFEMergeFragmentos**: se trata de una operación de bloqueo que combina fragmentos de su operador ascendente en un único bloque de soluciones para pasarlos a su operador descendente (a la inversa de). `DFESplitChunks`

**DFEMinus**— Toma una relación de entrada entre la derecha y la izquierda y conserva los valores de la relación izquierda que no tienen un valor correspondiente en la relación derecha, tal como se define en las variables de unión dadas. Si no hay superposición de variables en ambas relaciones, este operador simplemente devuelve la relación de entrada de la izquierda.

**DFENotExiste**: toma una relación de entrada entre la izquierda y la derecha y conserva los valores de la relación izquierda que no tienen un valor correspondiente en la relación derecha, tal como se define en las variables de combinación dadas. Si no hay superposición de variables en ambas relaciones, este operador devuelve una relación vacía.

**DFEOptionalUnir**: realiza una unión externa por la izquierda (también denominada unión OPCIONAL): las soluciones del lado izquierdo que tienen al menos un compañero de unión en el lado derecho se unen, y las soluciones del lado izquierdo sin un compañero de unión en el lado derecho se reenvían tal cual. Es una operación de bloqueo.

**DFEPipelineUnir**: une la entrada siguiendo el patrón de tuplas definido por el argumento. `pattern`

**DFEPipelineRangeCount**— Cuenta el número de soluciones que coinciden con un patrón dado y devuelve una única solución uniaria que contiene el valor de recuento.

**DFEPipelineEscanear**: escanea la base de datos en busca del `pattern` argumento dado, con o sin un filtro determinado en las columnas.

**DFEProject**— Toma varias columnas de entrada y proyecta solo las columnas deseadas.

**DFEReduce**— Realiza la función de agregación especificada en variables especificadas.

**DFERelationalUnir**: une la entrada del operador anterior en función de las claves de patrón especificadas mediante una combinación de fusión. Es una operación de bloqueo.

**DFERouteFragmentos**: toma los fragmentos de entrada de su único borde de entrada y los enruta a lo largo de sus múltiples bordes de salida.

**DFESelectFilas: este operador toma filas** de forma selectiva de sus soluciones de relaciones de entrada de la izquierda y las reenvía a su operador descendente. Las filas se seleccionan en función de los identificadores de línea proporcionados en la relación de entrada derecha del operador.

**DFESerialize**— Serializa los resultados finales de una consulta en una serialización de cadenas JSON, asignando cada solución de entrada al nombre de variable correspondiente. En el caso de resultados de nodos y bordes, estos resultados se serializan en un mapa de propiedades y metadatos de la entidad.

**DFESort**— Toma una relación de entrada y produce una relación ordenada en función de la clave de clasificación proporcionada.

**DFESplitByGroup**— Divide cada fragmento de entrada de un borde de entrada en fragmentos de salida más pequeños que corresponden a los grupos de filas identificados por fila IDs del fragmento de entrada correspondiente del otro borde de entrada.

**DFESplitFragmentos: divide cada fragmento de entrada individual en fragmentos** de salida más pequeños (a la inversa de). `DFEMergeChunks`

**DFEStreamingHashIndexBuild**— Versión en streaming de. `DFEHashIndexBuild`

**DFEStreamingGroupByHashIndex**— Versión en streaming de`DFEGroupByHashIndex`.

**DFESubquery**— Este operador aparece al principio de todos los planes y resume las partes del plan que se ejecutan en el [motor DFE](neptune-dfe-engine.md), que es el plan completo de OpenCypher.

**DFESymmetricHashJoin**— Une la entrada del operador anterior en función de las claves de patrón especificadas mediante una combinación hash. Es una operación sin bloqueo.

**DFESync**— Este operador es un operador de sincronización que admite planes sin bloqueo. Toma las soluciones de dos periferias entrantes y las envía a los periferias posteriores apropiadas. Para fines de sincronización, las entradas a lo largo de uno de estas periferias pueden almacenarse internamente en búfer. 

**DFETee**— Se trata de un operador de sucursales que envía el mismo conjunto de soluciones a varios operadores.

**DFETermResolución**: realiza una operación de localización o globalización en sus entradas, lo que da como resultado columnas de identificadores localizados o globalizados, respectivamente.

****: despliega listas de valores de una columna de entrada a la columna de salida como elementos individuales.

**DFEUnion**— Toma dos o más relaciones de entrada y produce una unión de esas relaciones utilizando el esquema de salida deseado.

**SolutionInjection**— Aparece antes que todo lo demás en el resultado explicativo, con un valor de 1 en la columna Unidades de salida. Sin embargo, no sirve para nada y en realidad no inyecta ninguna solución en el motor DFE.

**TermResolution**— Aparece al final de los planos y convierte los objetos del motor de Neptune en objetos de OpenCypher.

## Columnas en la salida de `explain` de openCypher
<a name="access-graph-opencypher-explain-columns"></a>

La información del plan de consultas que Neptune genera como resultado de explain de openCypher contiene tablas con un operador por fila. Esta tabla tiene las siguientes columnas:

**ID**: el identificador numérico de este operador del plan.

**Salida 1** (y **Salida 2**): los identificadores de los operadores que se encuentran más abajo de este operador. Puede haber como máximo dos operadores más abajo.

**Nombre**: el nombre de este operador.

**Argumentos**: cualquier detalle relevante para el operador. Incluye elementos como el esquema de entrada, el esquema de salida, el patrón (para `PipelineScan` y `PipelineJoin`), etc.

**Modo**: etiqueta que describe el comportamiento fundamental del operador. La mayor parte de esta columna está en blanco (`-`). Una excepción es `TermResolution`, donde el modo puede ser `id2value_opencypher`, que indica una resolución desde el identificador hasta el valor de openCypher.

**Unidades de entrada**: el número de soluciones que se pasan como entrada a este operador. Los operadores sin operadores por encima, como `DFEPipelineScan`, `SolutionInjections` y `DFESubquery`, sin un valor estático inyectado, tendrían un valor cero.

**Unidades de salida**: la cantidad de soluciones producidas como salida de este operador. `DFEDrain` es un caso especial en el que el número de soluciones que se están drenando se registra en `Units In` y `Units Out` siempre es cero.

**Relación**: la relación de `Units Out` a `Units In`.

**Tiempo (ms)**: el tiempo de CPU que consume este operador, en milisegundos.

## Salida de ejemplo básico de explain de openCypher
<a name="access-graph-opencypher-explain-basic-example"></a>

A continuación, se muestra un ejemplo básico de una salida de `explain` de openCypher: La consulta es una búsqueda de un nodo único en el conjunto de datos de rutas aéreas para un nodo con el código de aeropuerto `ATL` que se invoca `explain` utilizando el `details` modo en el formato de salida ASCII predeterminado.

Para invocar esta consulta`explain`:

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

```
aws neptunedata execute-open-cypher-explain-query \
  --endpoint-url https://your-neptune-endpoint:port \
  --open-cypher-query "MATCH (n {code: 'ATL'}) RETURN n" \
  --explain-mode details
```

Para obtener más información, consulte [execute-open-cypher-explain-query](https://docs.aws.amazon.com/cli/latest/reference/neptunedata/execute-open-cypher-explain-query.html) en 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_open_cypher_explain_query(
    openCypherQuery="MATCH (n {code: 'ATL'}) RETURN n",
    explainMode='details'
)

print(response['results'].read().decode('utf-8'))
```

Para ver ejemplos de AWS SDK en otros idiomas, consulte[AWS SDK](access-graph-opencypher-sdk.md).

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

```
awscurl https://your-neptune-endpoint:port/openCypher \
  --region us-east-1 \
  --service neptune-db \
  -X POST \
  -d "query=MATCH (n {code: 'ATL'}) RETURN n" \
  -d "explain=details"
```

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

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

```
curl https://your-neptune-endpoint:port/openCypher \
  -d "query=MATCH (n {code: 'ATL'}) RETURN n" \
  -d "explain=details"
```

------

La `explain` salida:

```
Query:
MATCH (n {code: 'ATL'}) RETURN n

╔════╤════════╤════════╤═══════════════════╤════════════════════╤═════════════════════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name              │ Arguments          │ Mode                │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════╪════════════════════╪═════════════════════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ SolutionInjection │ solutions=[{}]     │ -                   │ 0        │ 1         │ 0.00  │ 0         ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFESubquery       │ subQuery=subQuery1 │ -                   │ 0        │ 1         │ 0.00  │ 4.00      ║
╟────┼────────┼────────┼───────────────────┼────────────────────┼─────────────────────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ -      │ -      │ TermResolution    │ vars=[?n]          │ id2value_opencypher │ 1        │ 1         │ 1.00  │ 2.00      ║
╚════╧════════╧════════╧═══════════════════╧════════════════════╧═════════════════════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery1
╔════╤════════╤════════╤═══════════════════════╤══════════════════════════════════════════════════════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                  │ Arguments                                                                                                    │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪═══════════════════════╪══════════════════════════════════════════════════════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFEPipelineScan       │ pattern=Node(?n) with property 'code' as ?n_code2 and label 'ALL'                                            │ -    │ 0        │ 1         │ 0.00  │ 0.21      ║
║    │        │        │                       │ inlineFilters=[(?n_code2 IN ["ATL"^^xsd:string])]                                                            │      │          │           │       │           ║
║    │        │        │                       │ patternEstimate=1                                                                                            │      │          │           │       │           ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ -      │ DFEChunkLocalSubQuery │ subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#9d84f97c-c3b0-459a-98d5-955a8726b159/graph_1 │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 3      │ -      │ DFEProject            │ columns=[?n]                                                                                                 │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼───────────────────────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ -      │ -      │ DFEDrain              │ -                                                                                                            │ -    │ 1        │ 0         │ 0.00  │ 0.03      ║
╚════╧════════╧════════╧═══════════════════════╧══════════════════════════════════════════════════════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝


subQuery=http://aws.amazon.com/neptune/vocab/v01/dfe/past/graph#9d84f97c-c3b0-459a-98d5-955a8726b159/graph_1
╔════╤════════╤════════╤══════════════════════╤════════════════════════════════════════════════════════════╤══════╤══════════╤═══════════╤═══════╤═══════════╗
║ ID │ Out #1 │ Out #2 │ Name                 │ Arguments                                                  │ Mode │ Units In │ Units Out │ Ratio │ Time (ms) ║
╠════╪════════╪════════╪══════════════════════╪════════════════════════════════════════════════════════════╪══════╪══════════╪═══════════╪═══════╪═══════════╣
║ 0  │ 1      │ -      │ DFESolutionInjection │ outSchema=[?n, ?n_code2]                                   │ -    │ 0        │ 1         │ 0.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 1  │ 2      │ 3      │ DFETee               │ -                                                          │ -    │ 1        │ 2         │ 2.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 2  │ 4      │ -      │ DFEDistinctColumn    │ column=?n                                                  │ -    │ 1        │ 1         │ 1.00  │ 0.20      ║
║    │        │        │                      │ ordered=false                                              │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 3  │ 5      │ -      │ DFEHashIndexBuild    │ vars=[?n]                                                  │ -    │ 1        │ 1         │ 1.00  │ 0.04      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 4  │ 5      │ -      │ DFEPipelineJoin      │ pattern=Node(?n) with property 'ALL' and label '?n_label1' │ -    │ 1        │ 1         │ 1.00  │ 0.25      ║
║    │        │        │                      │ patternEstimate=3506                                       │      │          │           │       │           ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 5  │ 6      │ 7      │ DFESync              │ -                                                          │ -    │ 2        │ 2         │ 1.00  │ 0.02      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 6  │ 8      │ -      │ DFEForwardValue      │ -                                                          │ -    │ 1        │ 1         │ 1.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 7  │ 8      │ -      │ DFEForwardValue      │ -                                                          │ -    │ 1        │ 1         │ 1.00  │ 0.01      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 8  │ 9      │ -      │ DFEHashIndexJoin     │ -                                                          │ -    │ 2        │ 1         │ 0.50  │ 0.35      ║
╟────┼────────┼────────┼──────────────────────┼────────────────────────────────────────────────────────────┼──────┼──────────┼───────────┼───────┼───────────╢
║ 9  │ -      │ -      │ DFEDrain             │ -                                                          │ -    │ 1        │ 0         │ 0.00  │ 0.02      ║
╚════╧════════╧════════╧══════════════════════╧════════════════════════════════════════════════════════════╧══════╧══════════╧═══════════╧═══════╧═══════════╝
```

En el nivel superior, `SolutionInjection` aparece antes que todo lo demás, con 1 unidad de salida. Tenga en cuenta que, en realidad, no inyecta ninguna solución. Puede ver que el siguiente operador, `DFESubquery`, tiene 0 unidades.

Después de `SolutionInjection` en el nivel superior, están los operadores `DFESubquery` y `TermResolution`. `DFESubquery` encapsula las partes del plan de ejecución de consultas que se envían al [motor DFE](neptune-dfe-engine.md) (en el caso de las consultas de openCypher, el DFE ejecuta todo el plan de consultas). Todos los operadores del plan de consultas están anidados dentro de `subQuery1`, al que hace referencia `DFESubquery`. La única excepción es `TermResolution` que se materializa internamente IDs en objetos OpenCypher completamente serializados.

Todos los operadores que se desplazan hacia abajo hasta el motor DFE tienen nombres que comienzan con un prefijo `DFE`. Como se ha mencionado anteriormente, el DFE ejecuta todo el plan de consultas de openCypher, por lo que todos los operadores, excepto el operador `TermResolution` final, comienzan con `DFE`.

En el interior de `subQuery1`, puede haber cero o más operadores `DFEChunkLocalSubQuery` o `DFELoopSubQuery` que encapsulen una parte del plan de ejecución desplazado que se ejecuta en un mecanismo limitado por la memoria. `DFEChunkLocalSubQuery`contiene aquí un `SolutionInjection` que se utiliza como entrada para la subconsulta. Para buscar la tabla de esa subconsulta en la salida, busque la `subQuery=graph URI` especificada en la columna `Arguments` correspondiente al operador `DFEChunkLocalSubQuery` o `DFELoopSubQuery`.

En `subQuery1`, `DFEPipelineScan` con el `ID` 0, escanea la base de datos en busca de un `pattern` especificado. El patrón busca una entidad con la propiedad `code` guardada como variable `?n_code2` en todas las etiquetas (puede filtrar una etiqueta específica agregando `airport` a `n:airport`). El argumento `inlineFilters` muestra el filtrado de la propiedad `code`, que equivale a `ATL`.

A continuación, el operador `DFEChunkLocalSubQuery` une los resultados intermedios de una subconsulta que contiene `DFEPipelineJoin`. Esto asegura que en realidad `?n` sea un nodo, ya que el `DFEPipelineScan` anterior busca cualquier entidad con la propiedad `code`.