

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

# Ajustar consultas do Gremlin usando `explain` e `profile`
<a name="gremlin-traversal-tuning"></a>

[[Muitas vezes, você pode ajustar suas consultas do Gremlin no Amazon Neptune para obter um melhor desempenho, usando as informações disponíveis nos relatórios que você obtém do perfil e explicação do Neptune.](gremlin-profile-api.md)](gremlin-explain-api.md) APIs Para isso, é útil entender como o Neptune processa os percursos do Gremlin.

**Importante**  
Foi feita uma alteração na TinkerPop versão 3.4.11 que melhora a exatidão de como as consultas são processadas, mas, no momento, às vezes pode afetar seriamente o desempenho das consultas.  
Por exemplo, uma consulta desse tipo pode apresentar uma lentidão significativa:  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  out()
```
Os vértices após a etapa limite agora são buscados de uma forma não ideal por causa da alteração 3.4.11. TinkerPop Para evitar isso, é possível modificar a consulta adicionando a etapa barrier() a qualquer momento após `order().by()`. Por exemplo:  

```
g.V().hasLabel('airport').
  order().
    by(out().count(),desc).
  limit(10).
  barrier().
  out()
```
TinkerPop [3.4.11 foi habilitado na versão 1.0.5.0 do motor Neptune.](engine-releases-1.0.5.0.md)

## Noções básicas sobre o processamento de percursos do Gremlin no Neptune
<a name="gremlin-traversal-processing"></a>

Quando um percurso do Gremlin é enviado ao Neptune, há três processos principais que transformam o percurso em um plano de execução subjacente a ser executado pelo mecanismo. São eles: análise, conversão e otimização:

![Três processos transformam uma consulta do Gremlin em um plano de execução.](http://docs.aws.amazon.com/pt_br/neptune/latest/userguide/images/Gremlin_traversal_processing.png)


### O processo de análise de percurso
<a name="gremlin-traversal-processing-parsing"></a>

A primeira etapa do processamento de um percurso é analisá-lo em uma linguagem comum. [Em Neptune, essa linguagem comum é o conjunto TinkerPop de etapas que fazem parte da API. TinkerPop](http://tinkerpop.apache.org/javadocs/3.4.8/full/org/apache/tinkerpop/gremlin/process/traversal/Step.html) Cada uma dessas etapas representa uma unidade de cálculo dentro do percurso.

É possível enviar um percurso do Gremlin ao Neptune como uma string ou um bytecode. O endpoint REST e o método `submit()` do driver do cliente Java enviam percursos como strings, como neste exemplo:

```
client.submit("g.V()")
```

Aplicações e drivers de linguagem que usam [variantes de linguagem Gremlin (GLV)](https://tinkerpop.apache.org/docs/current/tutorials/gremlin-language-variants/) enviam percursos em bytecode.

### O processo de conversão de percurso
<a name="gremlin-traversal-processing-conversion"></a>

A segunda etapa no processamento de uma travessia é converter suas TinkerPop etapas em um conjunto de etapas de Netuno convertidas e não convertidas. A maioria das etapas na linguagem de consulta Apache TinkerPop Gremlin é convertida em etapas específicas do Neptune que são otimizadas para serem executadas no mecanismo Neptune subjacente. Quando uma TinkerPop etapa sem um equivalente de Netuno é encontrada em uma travessia, essa etapa e todas as etapas subsequentes na travessia são processadas pelo mecanismo de consulta. TinkerPop 

Para obter mais informações sobre quais etapas podem ser convertidas em quais circunstâncias, consulte [Suporte a etapas do Gremlin](gremlin-step-support.md).

### O processo de otimização de percurso
<a name="gremlin-traversal-processing-optimization"></a>

A etapa final do processamento de percurso é executar a série de etapas convertidas e não convertidas por meio do otimizador, para tentar determinar o melhor plano de execução. O resultado dessa otimização é o plano de execução que o mecanismo do Neptune processa.

## Usar a API `explain` do Gremlin no Neptune para ajustar consultas
<a name="gremlin-traversal-tuning-explain"></a>

A API de explicação do Neptune não é a mesma que a etapa `explain()` do Gremlin. Ela retorna o plano de execução final que o mecanismo do Neptune processaria ao executar a consulta. Como não executa nenhum processamento, ela retorna o mesmo plano, independentemente dos parâmetros usados, e sua saída não contém estatísticas sobre a execução real.

Examine o seguinte percurso simples que encontra todos os vértices do aeroporto para Anchorage:

```
g.V().has('code','ANC')
```

É possível executar esse percurso por meio da API `explain` do Neptune de duas maneiras. A primeira é fazer uma chamada REST para o endpoint de explicação, desta forma:

```
curl -X POST https://{{your-neptune-endpoint}}:{{port}}/gremlin/explain -d '{"gremlin":"g.V().has('code','ANC')"}'
```

A segunda é usar a magia de célula [%%gremlin](notebooks-magics.md#notebooks-cell-magics-gremlin) da bancada de trabalho do Neptune com o parâmetro `explain`. Isso transmite o percurso contido no corpo da célula para a API `explain` do Neptune e, depois, exibe a saída resultante quando você executa a célula:

```
%%gremlin explain

g.V().has('code','ANC')
```

A saída da API `explain` resultante descreve o plano de execução do Neptune para o percurso. Como você pode ver na imagem abaixo, o plano inclui cada uma das três etapas no pipeline de processamento:

![Explique a saída da API para um percurso simples do Gremlin.](http://docs.aws.amazon.com/pt_br/neptune/latest/userguide/images/Gremlin_explain_output_1.png)


### Ajustar um percurso observando as etapas que não são convertidas
<a name="gremlin-traversal-tuning-explain-non-converted-steps"></a>

Um dos primeiros itens a procurar na saída da API `explain` do Neptune são as etapas do Gremlin que não são convertidas em etapas nativas do Neptune. Em um plano de consulta, quando é encontrada uma etapa que não pode ser convertida em uma etapa nativa do Neptune, ela e todas as etapas subsequentes do plano são processadas pelo servidor do Gremlin.

No exemplo acima, todas as etapas no percurso foram convertidas. Vamos examinar a saída da API `explain` para este percurso:

```
g.V().has('code','ANC').out().choose(hasLabel('airport'), values('code'), constant('Not an airport'))
```

Como você pode ver na imagem abaixo, o Neptune não conseguiu converter a etapa `choose()`:

![Explique a saída da API na qual nem todas as etapas podem ser convertidas.](http://docs.aws.amazon.com/pt_br/neptune/latest/userguide/images/Gremlin_explain_output_2.png)


É possível executar algumas etapas para ajustar o desempenho do percurso. A primeira seria reescrevê-lo de forma a eliminar a etapa que não pôde ser convertida. Outra seria mover a etapa para o final do percurso para que todas as outras etapas possam ser convertidas em etapas nativas.

Um plano de consulta com etapas que não são convertidas nem sempre precisa ser ajustado. Se as etapas que não podem ser convertidas estiverem no final do percurso e estiverem relacionadas à forma como a saída é formatada e não à forma como o grafo é percorrido, elas poderão ter pouco efeito no desempenho.

### 
<a name="gremlin-traversal-tuning-explain-unindexed-lookups"></a>

Outro item a ser observado ao examinar a saída da API `explain` do Neptune são as etapas que não usam índices. O seguinte percurso encontra todos os aeroportos com voos que aterrissam em Anchorage:

```
g.V().has('code','ANC').in().values('code')
```

A saída da API de explicação para esse percurso é:

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============

g.V().has('code','ANC').in().values('code')

Original Traversal
==================
[GraphStep(vertex,[]), HasStep([code.eq(ANC)]), VertexStep(IN,vertex), PropertiesStep([code],value)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
            PatternNode[(?1, <code>, "ANC", ?) . project ask .]
            PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .]
            PatternNode[(?3, <~label>, ?4, <~>) . project ask .]
            PatternNode[(?3, ?7, ?8, <~>) . project ?3,?8 . ContainsFilter(?7 in (<code>)) .]
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <code>, "ANC", ?) . project ?1 .], {estimatedCardinality=1}
            PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=INFINITY}
            PatternNode[(?3, ?7=<code>, ?8, <~>) . project ?3,?8 .], {estimatedCardinality=7564}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 26

WARNING: reverse traversal with no edge label(s) - .in() / .both() may impact query performance
```

A mensagem `WARNING` na parte inferior da saída ocorre porque a etapa `in()` no percurso não pode ser processada usando um dos três índices mantidos pelo Neptune (consulte [Como as declarações são indexadas no Neptune](feature-overview-storage-indexing.md) e [Declarações do Gremlin no Neptune](gremlin-explain-background-statements.md)). Como a etapa `in()` não contém filtro de borda, ela não pode ser resolvida usando o índice `SPOG`, `POGS` ou `GPSO`. Em vez disso, o Neptune deve realizar uma verificação de união para encontrar os vértices solicitados, o que é muito menos eficiente.

Há duas maneiras de ajustar o percurso nessa situação. A primeira é adicionar um ou mais critérios de filtragem à etapa `in()` para que uma pesquisa indexada possa ser usada para resolver a consulta. Para o exemplo acima, pode ser:

```
g.V().has('code','ANC').in('route').values('code')
```

A saída da API `explain` do Neptune para o percurso revisado não contém mais a mensagem `WARNING`:

```
*******************************************************
                Neptune Gremlin Explain
*******************************************************

Query String
============

g.V().has('code','ANC').in('route').values('code')

Original Traversal
==================
[GraphStep(vertex,[]), HasStep([code.eq(ANC)]), VertexStep(IN,[route],vertex), PropertiesStep([code],value)]

Converted Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <~label>, ?2, <~>) . project distinct ?1 .]
            PatternNode[(?1, <code>, "ANC", ?) . project ask .]
            PatternNode[(?3, ?5, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) . ContainsFilter(?5 in (<route>)) .]
            PatternNode[(?3, <~label>, ?4, <~>) . project ask .]
            PatternNode[(?3, ?7, ?8, <~>) . project ?3,?8 . ContainsFilter(?7 in (<code>)) .]
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Optimized Traversal
===================
Neptune steps:
[
    NeptuneGraphQueryStep(PropertyValue) {
        JoinGroupNode {
            PatternNode[(?1, <code>, "ANC", ?) . project ?1 .], {estimatedCardinality=1}
            PatternNode[(?3, ?5=<route>, ?1, ?6) . project ?1,?3 . IsEdgeIdFilter(?6) .], {estimatedCardinality=32042}
            PatternNode[(?3, ?7=<code>, ?8, <~>) . project ?3,?8 .], {estimatedCardinality=7564}
        }, annotations={path=[Vertex(?1):GraphStep, Vertex(?3):VertexStep, PropertyValue(?8):PropertiesStep], maxVarId=9}
    },
    NeptuneTraverserConverterStep
]

Predicates
==========
# of predicates: 26
```

Outra opção, se você estiver executando muitos percursos desse tipo, é executá-los em um cluster de banco de dados do Neptune que tenha o índice opcional `OSGP` habilitado (consulte [Habilitar um índice OSGP](feature-overview-storage-indexing.md#feature-overview-storage-indexing-osgp)). Habilitar um índice `OSGP` tem desvantagens:
+ Ele deve ser habilitado em um cluster de banco de dados antes do carregamento de dados.
+ As taxas de inserção para vértices e bordas podem diminuir em até 23%.
+ O uso do armazenamento aumentará em cerca de 20%.
+ Consultas de leitura que dispersam solicitações em todos os índices podem ter latências maiores.

Ter um índice `OSGP` faz muito sentido para um conjunto restrito de padrões de consulta, mas, a menos que você os execute com frequência, geralmente é preferível tentar garantir que os percursos escritos possam ser resolvidos usando os três índices principais.

### Usar um grande número de predicados
<a name="gremlin-traversal-tuning-explain-many-predicates"></a>

O Neptune trata cada rótulo de borda e cada nome distinto de propriedade de vértice ou borda no grafo como um predicado e foi projetado por padrão para funcionar com um número relativamente baixo de predicados distintos. Quando você tem mais do que alguns milhares de predicados em seus dados de grafo, o desempenho pode diminuir.

A saída `explain` do Neptune avisará se for esse o caso:

```
Predicates
==========
# of predicates: 9549
WARNING: high predicate count (# of distinct property names and edge labels)
```

Se não for conveniente revisar o modelo de dados para reduzir o número de rótulos e propriedades e, portanto, o número de predicados, a melhor maneira de ajustar os percursos é executá-los em um cluster de banco de dados com o índice `OSGP` habilitado, conforme abordado acima.

## Usar a API `profile` do Gremlin no Neptune para ajustar percursos
<a name="gremlin-traversal-tuning-profile"></a>

A API `profile` do Neptune é bem diferente da etapa `profile()` do Gremlin. Assim como a API `explain`, sua saída inclui o plano de consulta que o mecanismo do Neptune usa ao executar o percurso. Além disso, a saída `profile` inclui estatísticas reais de execução do percurso, considerando como seus parâmetros são definidos.

Novamente, considere o percurso simples que encontra todos os vértices do aeroporto para Anchorage:

```
g.V().has('code','ANC')
```

Assim como na API `explain`, é possível invocar a API `profile` usando uma chamada REST:

```
curl -X POST https://{{your-neptune-endpoint}}:{{port}}/gremlin/profile -d '{"gremlin":"g.V().has('code','ANC')"}'
```

Também é possível usar a magia de célula [%%gremlin](notebooks-magics.md#notebooks-cell-magics-gremlin) da bancada de trabalho do Neptune com o parâmetro `profile`. Isso transmite o percurso contido no corpo da célula para a API `profile` do Neptune e, depois, exibe a saída resultante quando você executa a célula:

```
%%gremlin profile

g.V().has('code','ANC')
```

A saída da API `profile` resultante contém o plano de execução do Neptune para o percurso e estatísticas sobre a execução do plano, como você pode ver nesta imagem:

![Um exemplo da saída da API profile do Neptune.](http://docs.aws.amazon.com/pt_br/neptune/latest/userguide/images/Gremlin_profile_output_1.png)


Na saída `profile`, a seção do plano de execução contém somente o plano de execução final para o percurso, não as etapas intermediárias. A seção do pipeline contém as operações físicas executadas, bem como o tempo real (em milissegundos) que a execução do percurso levou. A métrica de runtime é extremamente útil para comparar os tempos que duas versões diferentes de um percurso levam à medida que você as otimiza.

**nota**  
O runtime inicial de um percurso geralmente é maior do que os runtimes subsequentes, porque o primeiro faz com que os dados relevantes sejam armazenados em cache.

A terceira seção da saída `profile` contém estatísticas de execução e os resultados do percurso. Para ver como essas informações podem ser úteis para ajustar um percurso, considere o seguinte percurso, que encontra todos os aeroportos cujo nome começa com “Anchora” e todos os aeroportos acessíveis em dois saltos a partir desses aeroportos, retornando códigos de aeroporto, rotas de voo e distâncias:

```
%%gremlin profile

g.withSideEffect("Neptune#fts.endpoint", "{your-OpenSearch-endpoint-URL").
    V().has("city", "Neptune#fts Anchora~").
    repeat(outE('route').inV().simplePath()).times(2).
    project('Destination', 'Route').
        by('code').
        by(path().by('code').by('dist'))
```

### Métricas de percurso na saída da API `profile` do Neptune
<a name="gremlin-traversal-tuning-profile-traversal-metrics"></a>

O primeiro conjunto de métricas que está disponível em todas as saídas `profile` são as métricas de percurso. Elas são semelhantes às métricas de etapa `profile()` do Gremlin, com algumas diferenças:

```
Traversal Metrics
=================
Step                                                               Count  Traversers       Time (ms)    % Dur
-------------------------------------------------------------------------------------------------------------
NeptuneGraphQueryStep(Vertex)                                       3856        3856          91.701     9.09
NeptuneTraverserConverterStep                                       3856        3856          38.787     3.84
ProjectStep([Destination, Route],[value(code), ...                  3856        3856         878.786    87.07
  PathStep([value(code), value(dist)])                              3856        3856         601.359
                                            >TOTAL                     -           -        1009.274        -
```

A primeira coluna da tabela de métricas de percurso lista as etapas executadas pelo percurso. As duas primeiras etapas são geralmente as etapas específicas do Neptune, `NeptuneGraphQueryStep` e `NeptuneTraverserConverterStep`.

`NeptuneGraphQueryStep` representa o tempo de execução de toda a parte do percurso que poderia ser convertida e executada nativamente pelo mecanismo do Neptune.

`NeptuneTraverserConverterStep`representa o processo de conversão da saída dessas etapas convertidas em TinkerPop percursos que permitem que etapas que não puderam ser convertidas, se houver, sejam processadas ou retornem os resultados em um TinkerPop formato compatível.

No exemplo acima, temos várias etapas não convertidas, então vemos que cada uma dessas TinkerPop etapas (`ProjectStep`,`PathStep`) aparece como uma linha na tabela.

[A segunda coluna na tabela,`Count`, relata o número de atravessadores *representados* que passaram pela etapa, enquanto a terceira coluna,`Traversers`, relata o número de atravessadores que passaram por essa etapa, conforme explicado na documentação da etapa do TinkerPop perfil.](https://tinkerpop.apache.org/docs/current/reference/#profile-step)

Em nosso exemplo, há 3.856 vértices e 3.856 percursos gerados pela `NeptuneGraphQueryStep`, e esses números permanecem os mesmos durante todo o processamento restante porque `ProjectStep` e `PathStep` estão formatando os resultados, não os filtrando.

**nota**  
Ao contrário TinkerPop disso, o motor Neptune não otimiza o desempenho *aumentando suas* etapas. `NeptuneGraphQueryStep` `NeptuneTraverserConverterStep` O aumento de volume é a TinkerPop operação que combina travessas no mesmo vértice para reduzir a sobrecarga operacional, e é isso que faz com que os `Count` números e sejam diferentes. `Traversers` Como o aumento de volume ocorre apenas nas etapas às quais Netuno delega, e não nas etapas que TinkerPop o Netuno manipula nativamente, as colunas e raramente diferem. `Count` `Traverser`

A coluna Tempo informa o número de milissegundos que a etapa levou, e a coluna `% Dur` informa qual a porcentagem do tempo total de processamento da etapa. Essas são as métricas que indicam onde concentrar seus esforços de ajuste, mostrando as etapas que levaram mais tempo.

### Métricas de operação de índice na saída da API `profile` do Neptune
<a name="gremlin-traversal-tuning-profile-index-operations"></a>

Outro conjunto de métricas na saída da API do perfil do Neptune são as operações de indexação:

```
Index Operations
================
Query execution:
    # of statement index ops: 23191
    # of unique statement index ops: 5960
    Duplication ratio: 3.89
    # of terms materialized: 0
```

Elas relatam:
+ O número total de pesquisas de índice.
+ O número de pesquisas de índice exclusivas realizadas.
+ A proporção entre o total de pesquisas de índices e as exclusivas. Uma proporção menor indica menor redundância.
+ O número de termos materializados do dicionário de termos.

### Métricas repetidas na saída da API `profile` do Neptune
<a name="gremlin-traversal-tuning-profile-repeat-metrics"></a>

Se o percurso usar uma etapa `repeat()` como no exemplo acima, uma seção que contém métricas repetidas será exibida na saída `profile`:

```
Repeat Metrics
==============
Iteration  Visited   Output    Until     Emit     Next
------------------------------------------------------
        0        2        0        0        0        2
        1       53        0        0        0       53
        2     3856     3856     3856        0        0
------------------------------------------------------
              3911     3856     3856        0       55
```

Elas relatam:
+ A contagem de loops de uma linha (a coluna `Iteration`).
+ O número de elementos visitados pelo loop (a coluna `Visited`).
+ O número de elementos gerados pelo loop (a coluna `Output`).
+ O último elemento gerado pelo loop (a coluna `Until`).
+ O número de elementos emitidos pelo loop (a coluna `Emit`).
+ O número de elementos transmitidos do loop para o loop subsequente (a `Next` coluna).

Essas métricas repetidas são muito úteis para entender o fator de ramificação do percurso, para ter uma ideia de quanto trabalho está sendo feito pelo banco de dados. Você pode usar esses números para diagnosticar problemas de desempenho, especialmente quando o mesmo percurso tem um desempenho drasticamente diferente com parâmetros distintos.

### Métricas de pesquisa de texto completo na saída da API `profile` do Neptune
<a name="gremlin-traversal-tuning-profile-fts-metrics"></a>

Quando um percurso usa uma [pesquisa de texto completo](full-text-search.md), como no exemplo acima, uma seção que contém as métricas de pesquisa de texto completo (FTS) aparece na saída `profile`:

```
FTS Metrics
==============
SearchNode[(idVar=?1, query=Anchora~, field=city) . project ?1 .],
    {endpoint=your-OpenSearch-endpoint-URL, incomingSolutionsThreshold=1000, estimatedCardinality=INFINITY,
    remoteCallTimeSummary=[total=65, avg=32.500000, max=37, min=28],
    remoteCallTime=65, remoteCalls=2, joinTime=0, indexTime=0, remoteResults=2}

    2 result(s) produced from SearchNode above
```

Isso mostra a consulta enviada ao cluster ElasticSearch (ES) e relata várias métricas sobre a interação com ElasticSearch que podem ajudá-lo a identificar problemas de desempenho relacionados à pesquisa de texto completo:
+ Informações resumidas sobre as chamadas para o ElasticSearch índice:
  + O número total de milissegundos exigido por todas as chamadas remotas para atender à consulta (`total`).
  + O número médio de milissegundos gastos em uma remoteCall (`avg`).
  + O número mínimo de milissegundos gastos em uma remoteCall (`min`).
  + O número máximo de milissegundos gastos em uma remoteCall (`max`).
+ Tempo total consumido por chamadas remotas para ElasticSearch ()`remoteCallTime`.
+ O número de chamadas remotas feitas para ElasticSearch ()`remoteCalls`.
+ O número de milissegundos gastos em junções de ElasticSearch resultados ()`joinTime`.
+ O número de milissegundos gastos em pesquisas de índice (`indexTime`).
+ O número total de resultados retornados por ElasticSearch (`remoteResults`).