Solução de problemas de consultas lentas troubleshooting-slow-queries
Classificações de consulta lenta slow-query-classifications
Há três classificações principais de consultas lentas no AEM, listadas por gravidade:
-
Consultas sem índice
- Consultas que não resolvem em um índice e percorrem o conteúdo do JCR para coletar resultados
-
Consultas pouco restritas (ou com escopo)
- Consultas que resolvem um índice, mas devem percorrer todas as entradas de índice para coletar resultados
-
Consultas de conjunto de resultados grandes
- Consultas que retornam um grande número de resultados
As duas primeiras classificações de consultas (sem índice e pouco restritas) são lentas. Eles estão lentos porque forçam o mecanismo de consulta do Oak a inspecionar cada resultado potencial (nó de conteúdo ou entrada de índice) para identificar qual pertence ao conjunto de resultados real.
O ato de inspecionar cada resultado potencial é o que é chamado de Travessia.
Como cada resultado potencial deve ser inspecionado, o custo para determinar o conjunto de resultados real cresce linearmente com o número de resultados potenciais.
A adição de restrições de consulta e índices de ajuste permite que os dados de índice sejam armazenados em um formato otimizado, permitindo uma recuperação rápida de resultados e reduz ou elimina a necessidade de inspeção linear de conjuntos de resultados em potencial.
No AEM 6.3, por padrão, quando um percurso de 100.000 é atingido, o query falha e lança uma exceção. Esse limite não existe por padrão nas versões AEM anteriores ao AEM 6.3, mas pode ser definido por meio da configuração OSGi Apache Rabbit Query Engine Settings e do bean JMX QueryEngineSettings (propriedade LimitReads).
Detecção de consultas sem índice detecting-index-less-queries
Durante o desenvolvimento during-development
Explique todas as consultas e certifique-se de que seus planos de consulta não contenham a explicação /* traverse. Exemplo de plano de consulta de passagem:
- PLANO:
[nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */
Post-Implantação post-deployment
-
Monitorar o
error.log
para consultas de percurso sem índice:*INFO* org.apache.jackrabbit.oak.query.QueryImpl Traversal query (query without index) ... ; consider creating and index
- Essa mensagem só será registrada se nenhum índice estiver disponível e se a consulta potencialmente atravessar muitos nós. As mensagens não são registradas se um índice estiver disponível, mas a quantidade de passagem é pequena e, portanto, rápida.
-
Visite o console de operações AEM Desempenho da consulta e Explicar consultas lentas procurando explicações de percurso ou nenhuma explicação de consulta de índice.
Detecção de consultas mal restritas detecting-poorly-restricted-queries
Durante o desenvolvimento during-development-1
Explique todas as consultas e verifique se elas são resolvidas em um índice ajustado para corresponder às restrições de propriedade da consulta.
- A cobertura do plano de consulta ideal tem
indexRules
para todas as restrições de propriedade e, no mínimo, para as restrições de propriedade mais rigorosas na consulta. - Consultas que classificam resultados devem ser resolvidas para um Índice de Propriedade Lucene com regras de índice para as propriedades classificadas por propriedades que definem
orderable=true.
Por exemplo, o padrão cqPageLucene
não tem uma regra de índice para jcr:content/cq:tags
for-example-the-default-cqpagelucene-does-not-have-an-index-rule-for-jcr-content-cq-tags
Antes de adicionar a regra de índice cq:tags
-
Regra de Índice cq:tags
- Não existe pronto para uso
-
Consulta do Construtor de Consultas
code language-js type=cq:Page property=jcr:content/cq:tags property.value=my:tag
-
Plano de consulta
[cq:Page] as [a] /* lucene:cqPageLucene(https://experienceleague.adobe.com/oak:index/cqPageLucene?lang=pt-BR) *:* where [a].[jcr:content/cq:tags] = 'my:tag' */
Esta consulta é resolvida para o índice cqPageLucene
, mas como nenhuma regra de índice de propriedade existe para jcr:content
ou cq:tags
, quando esta restrição é avaliada, todos os registros no índice cqPageLucene
são verificados para determinar uma correspondência. Dessa forma, se o índice contiver 1 milhão de nós cq:Page
, 1 milhão de registros será verificado para determinar o conjunto de resultados.
Depois de adicionar a regra de índice cq:tags
-
Regra de Índice cq:tags
code language-js /oak:index/cqPageLucene/indexRules/cq:Page/properties/cqTags @name=jcr:content/cq:tags @propertyIndex=true
-
Consulta do Construtor de Consultas
code language-js type=cq:Page property=jcr:content/cq:tags property.value=myTagNamespace:myTag
-
Plano de consulta
[cq:Page] as [a] /* lucene:cqPageLucene(https://experienceleague.adobe.com/oak:index/cqPageLucene?lang=pt-BR) jcr:content/cq:tags:my:tag where [a].[jcr:content/cq:tags] = 'my:tag' */
A adição de indexRule para jcr:content/cq:tags
no índice cqPageLucene
permite que os dados do cq:tags
sejam armazenados de forma otimizada.
Quando uma consulta com a restrição jcr:content/cq:tags
é executada, o índice pode pesquisar resultados por valor. Isso significa que se 100 nós cq:Page
tiverem myTagNamespace:myTag
como um valor, somente esses 100 resultados serão retornados, e os outros 999.000 serão excluídos das verificações de restrição, melhorando o desempenho por um fator de 10.000.
Mais restrições de consulta reduzem os conjuntos de resultados qualificados e otimizam ainda mais a otimização da consulta.
Da mesma forma, sem uma regra de índice extra para a propriedade cq:tags
, mesmo uma consulta de texto completo com uma restrição em cq:tags
teria um desempenho inadequado, pois os resultados do índice retornariam todas as correspondências de texto completo. A restrição em cq:tags seria filtrada após.
Outra causa da filtragem pós-índice são as Listas de controle de acesso, que muitas vezes são perdidas durante o desenvolvimento. Tente garantir que a consulta não retorne caminhos que podem ser inacessíveis para o usuário. Isso pode ser feito por uma estrutura de conteúdo melhor, juntamente com o fornecimento de restrições de caminho relevantes na consulta.
Uma maneira útil de identificar se o índice Lucene está retornando muitos resultados para retornar um pequeno subconjunto como resultado de consulta é habilitar logs DEBUG para org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndex
. Isso permite que você veja quantos documentos estão sendo carregados a partir do índice. O número de resultados eventuais versus o número de documentos carregados não deve ser desproporcional. Para obter mais informações, consulte Log.
Post-Implantação post-deployment-1
-
Monitorar o
error.log
para consultas de percurso:*WARN* org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor Traversed ### nodes ... consider creating an index or changing the query
-
Visite o console de operações AEM Desempenho da consulta e Explicar consultas lentas procurando planos de consulta que não resolvem restrições de propriedade de consulta para regras de propriedade de índice.
Detecção de consultas grandes de conjuntos de resultados detecting-large-result-set-queries
Durante o desenvolvimento during-development-2
Defina limites baixos para oak.queryLimitInMemory (por exemplo, 10000) e oak.queryLimitReads (por exemplo, 5000) e otimize a consulta cara ao acessar um UnsupportedOperationException dizendo "A consulta leu mais do que x nós…"
A definição de limites baixos ajuda a evitar consultas que consomem muitos recursos (ou seja, sem o suporte de qualquer índice ou com o suporte de um índice de cobertura menor). Por exemplo, uma consulta que lê um milhão de nós levaria a muita I/O e afetaria negativamente o desempenho geral do aplicativo. Portanto, qualquer query que falhar devido aos limites acima devem ser analisados e otimizados.
Post-Implantação post-deployment-2
-
Monitore os logs de consultas que acionam travessia de nó grande ou consumo de memória de heap grande : "
*WARN* ... java.lang.UnsupportedOperationException: The query read or traversed more than 100000 nodes. To avoid affecting other tasks, processing was stopped.
- Otimize a query para reduzir o número de nós percorridos.
-
Monitore os logs para consultas que acionam grande consumo de memória de heap:
*WARN* ... java.lang.UnsupportedOperationException: The query read more than 500000 nodes in memory. To avoid running out of memory, processing was stopped
- Otimize o query para reduzir o consumo de memória da pilha.
Para versões do AEM 6.0 - 6.2, é possível ajustar o limite para passagem de nó por meio de parâmetros JVM no script de inicialização do AEM para evitar que grandes consultas sobrecarreguem o ambiente. Os valores recomendados são:
-Doak.queryLimitInMemory=500000
-Doak.queryLimitReads=100000
No AEM 6.3, os dois parâmetros acima são pré-configurados por padrão e podem ser modificados por meio do OSGi QueryEngineSettings.
Mais informações disponíveis em: https://jackrabbit.apache.org/oak/docs/query/query-engine.html#Slow_Queries_and_Read_Limits
Ajuste do desempenho da consulta query-performance-tuning
O lema da otimização do desempenho da consulta no AEM é:
"Quanto mais restrições, melhor."
Os itens a seguir descrevem ajustes recomendados para garantir o desempenho da consulta. Primeiro, ajuste a consulta, uma atividade menos invasiva e, em seguida, se necessário, ajuste as definições de índice.
Ajustando a Instrução Query adjusting-the-query-statement
O AEM é compatível com os seguintes idiomas de consulta:
- Query Builder
- JCR-SQL2
- XPath
O exemplo a seguir usa o Construtor de consultas porque é a linguagem de consulta mais comum usada por desenvolvedores do AEM. No entanto, os mesmos princípios são aplicáveis ao JCR-SQL2 e ao XPath.
- Adicione uma restrição nodetype para que a consulta seja resolvida para um Índice de Propriedade Lucene existente.
-
Consulta não otimizada
code language-js property=jcr:content/contentType property.value=article-page
-
Consulta otimizada
code language-js type=cq:Page property=jcr:content/contentType property.value=article-page
Consultas sem uma restrição de tipo de nó forçam o AEM a assumir o tipo de nó
nt:base
, do qual todo nó no AEM é um subtipo, resultando efetivamente em nenhuma restrição de tipo de nó.A configuração
type=cq:Page
restringe esta consulta a somentecq:Page
nós e resolve a consulta para cqPageLucene de AEM, limitando os resultados a um subconjunto de nós (somentecq:Page
nós) em AEM.
- Ajuste a restrição nodetype da consulta para que a consulta seja resolvida como um Índice de propriedade Lucene existente.
-
Consulta não otimizada
code language-js type=nt:hierarchyNode property=jcr:content/contentType property.value=article-page
-
Consulta otimizada
code language-js type=cq:Page property=jcr:content/contentType property.value=article-page
nt:hierarchyNode
é o nodetype pai decq:Page
. Supondo quejcr:content/contentType=article-page
seja aplicado apenas acq:Page
nós por meio do aplicativo personalizado Adobe, essa consulta retorna apenascq:Page
nós, ondejcr:content/contentType=article-page
. No entanto, esse fluxo é uma restrição abaixo do ideal, pois:- Outro nó herda de
nt:hierarchyNode
(por exemplo,dam:Asset
) adicionando desnecessariamente ao conjunto de resultados potenciais. - Não existe índice fornecido pelo AEM para
nt:hierarchyNode
, no entanto, já que há um índice fornecido paracq:Page
.
A configuração
type=cq:Page
restringe esta consulta a apenascq:Page
nós e resolve a consulta para cqPageLucene de AEM, limitando os resultados a um subconjunto de nós (somente nós cq:Page) em AEM. - Outro nó herda de
- Ou ajuste as restrições de propriedade para que a consulta seja resolvida como um Índice de propriedade existente.
-
Consulta não otimizada
code language-js property=jcr:content/contentType property.value=article-page
-
Consulta otimizada
code language-js property=jcr:content/sling:resourceType property.value=my-site/components/structure/article-page
Alterar a restrição de propriedade de
jcr:content/contentType
(um valor personalizado) para a propriedade conhecidasling:resourceType
permite que a consulta resolva para o índice de propriedadeslingResourceType
que indexa todo o conteúdo porsling:resourceType
.Os índices de propriedade (em oposição aos índices de propriedade Lucene) são usados melhor quando a consulta não discerne por nodetype e uma única restrição de propriedade domina o conjunto de resultados.
- Adicione a restrição de caminho mais estreita possível à consulta. Por exemplo, prefira
/content/my-site/us/en
a/content/my-site
, ou/content/dam
a/
.
-
Consulta não otimizada
code language-js type=cq:Page path=/content property=jcr:content/contentType property.value=article-page
-
Consulta otimizada
code language-js type=cq:Page path=/content/my-site/us/en property=jcr:content/contentType property.value=article-page
O escopo da restrição de caminho de
path=/content
parapath=/content/my-site/us/en
permite que os índices reduzam o número de entradas de índice que devem ser inspecionadas. Quando a consulta puder restringir bem o caminho, além de apenas/content
ou/content/dam
, verifique se o índice temevaluatePathRestrictions=true
.Observe que o uso de
evaluatePathRestrictions
aumenta o tamanho do índice.
- Quando possível, evite funções de consulta e operações de consulta como:
LIKE
efn:XXXX
à medida que seus custos forem dimensionados com o número de resultados baseados em restrição.
-
Consulta não otimizada
code language-js type=cq:Page property=jcr:content/contentType property.operation=like property.value=%article%
-
Consulta otimizada
code language-js type=cq:Page fulltext=article fulltext.relPath=jcr:content/contentType
A condição LIKE é lenta para ser avaliada porque nenhum índice pode ser usado se o texto começar com um curinga ("%…'). A condição jcr:contains permite o uso de um índice de texto completo e, portanto, é preferível. É necessário que o Índice de Propriedade Lucene resolvido tenha indexRule para
jcr:content/contentType
comanalayzed=true
.Pode ser mais difícil otimizar o uso de funções de consulta como
fn:lowercase(..)
, pois não há equivalentes mais rápidos (fora de configurações mais complexas e invasivas do analisador de índice). É melhor identificar outras restrições de escopo para melhorar o desempenho geral da consulta, exigindo que as funções operem no menor conjunto possível de resultados em potencial.
-
Este ajuste é específico do Construtor de Consultas e não se aplica a JCR-SQL2 ou XPath.
Use guessTotal do Construtor de Consulta quando o conjunto completo de resultados for não imediatamente necessário.
-
Consulta não otimizada
code language-js type=cq:Page path=/content
-
Consulta otimizada
code language-js type=cq:Page path=/content p.guessTotal=100
Para casos em que a execução da consulta é rápida, mas o número de resultados é grande, p.
guessTotal
é uma otimização crítica para consultas do Construtor de Consultas.p.guessTotal=100
instrui o Construtor de Consultas a coletar apenas os primeiros 100 resultados. E, para definir um sinalizador booleano indicando se pelo menos mais um resultado existe (mas não quantos mais, já que contar esse número resulta em lentidão). Essa otimização é excelente para casos de uso de paginação ou carregamento infinito, em que apenas um subconjunto de resultados é exibido de forma incremental. -
Ajuste de índice existente existing-index-tuning
-
Se a consulta ideal for resolvida como um Índice de propriedade, não há mais nada a ser feito, pois os Índices de propriedade são ajustáveis minimamente.
-
Caso contrário, a consulta deve ser resolvida para um Índice de propriedades Lucene. Se nenhum índice puder ser resolvido, vá para Criação de um índice.
-
Conforme necessário, converta a consulta para XPath ou JCR-SQL2.
-
Consulta do Construtor de Consultas
code language-js query type=cq:Page path=/content/my-site/us/en property=jcr:content/contentType property.value=article-page orderby=@jcr:content/publishDate orderby.sort=desc
-
XPath gerado a partir da consulta do Construtor de Consultas
code language-js /jcr:root/content/my-site/us/en//element(*, cq:Page)[jcr:content/@contentType = 'article-page'] order by jcr:content/@publishDate descending
-
-
Forneça o XPath (ou JCR-SQL2) ao Oak Index Definition Generator em
https://oakutils.appspot.com/generate/index
para que você possa gerar a definição otimizada do Índice de Propriedades Lucene.Definição de Índice de Propriedade Lucene gerada
code language-xml - evaluatePathRestrictions = true - compatVersion = 2 - type = "lucene" - async = "async" - jcr:primaryType = oak:QueryIndexDefinition + indexRules + cq:Page + properties + contentType - name = "jcr:content/contentType" - propertyIndex = true + publishDate - ordered = true - name = "jcr:content/publishDate"
-
Mescle manualmente a definição gerada no Índice de propriedades Lucene existente de forma aditiva. Tenha cuidado para não remover configurações existentes, pois elas podem ser usadas para atender a outras consultas.
- Localize o Índice de propriedades Lucene existente que cobre cq:Page (usando o Gerenciador de índice). Neste caso,
/oak:index/cqPageLucene
. - Identifique o delta de configuração entre a definição de índice otimizado (Etapa #4) e o índice existente (https://experienceleague.adobe.com/oak:index/cqPageLucene?lang=pt-BR) e adicione as configurações ausentes do índice otimizado à definição de índice existente.
- De acordo com as Práticas recomendadas de reindexação do AEM, uma atualização ou reindexação está em ordem, com base no fato de o conteúdo existente poder ser afetado por essa alteração de configuração de índice.
- Localize o Índice de propriedades Lucene existente que cobre cq:Page (usando o Gerenciador de índice). Neste caso,
Criar um novo índice create-a-new-index
-
Verifique se a consulta não resolve um Índice de Propriedade Lucene existente. Se isso acontecer, consulte a seção acima sobre ajuste e índice existente.
-
Conforme necessário, converta a consulta para XPath ou JCR-SQL2.
-
Consulta do Construtor de Consultas
code language-js type=myApp:Author property=firstName property.value=ira
-
XPath gerado a partir da consulta do Construtor de Consultas
code language-js //element(*, myApp:Page)[@firstName = 'ira']
-
-
Forneça o XPath (ou JCR-SQL2) ao Oak Index Definition Generator em
https://oakutils.appspot.com/generate/index
para que você possa gerar a definição otimizada do Índice de Propriedades Lucene.Definição de Índice de Propriedade Lucene gerada
code language-xml - compatVersion = 2 - type = "lucene" - async = "async" - jcr:primaryType = oak:QueryIndexDefinition + indexRules + myApp:AuthorModel + properties + firstName - name = "firstName" - propertyIndex = true
-
Implante a definição do Índice de propriedade Lucene gerada.
Adicione a definição XML fornecida pelo Oak Index Definition Generator para o novo índice ao projeto AEM que gerencia as definições de índice Oak (lembre-se, trate as definições de índice Oak como código, já que o código depende delas).
Implante e teste o novo índice seguindo o ciclo de vida normal de desenvolvimento de software AEM e verifique se a consulta é resolvida para o índice e se a consulta tem desempenho.
Na implantação inicial desse índice, o AEM preenche o índice com os dados necessários.
Quando as consultas sem índice e de percurso estão OK? when-index-less-and-traversal-queries-are-ok
Devido à arquitetura de conteúdo flexível do AEM, é difícil prever e garantir que os percursos das estruturas de conteúdo não evoluam ao longo do tempo para serem inaceitavelmente grandes.
Portanto, verifique se os índices atendem às consultas, exceto se a combinação de restrição de caminho e restrição de tipo de nó garantir que menos de 20 nós sejam percorridos.
Ferramentas de desenvolvimento de query query-development-tools
Adobe suportado adobe-supported
-
Depurador do Construtor de Consultas
- Uma WebUI para executar consultas do Construtor de consultas e gerar o XPath de suporte (para uso em Explicar consulta ou Gerador de definição de índice Oak).
- No AEM em /libs/cq/search/content/querydebug.html
-
CRXDE Lite - Ferramenta de consulta
- Uma WebUI para executar consultas XPath e JCR-SQL2.
- No AEM em /crx/de/index.jsp > Ferramentas > Consulta…
-
- Um painel de Operações do AEM que fornece uma explicação detalhada (Plano de consulta, tempo de consulta e número de resultados) para qualquer consulta XPATH ou JCR-SQL2.
-
- Um painel de operações do AEM listando as recentes consultas lentas e populares executadas no AEM.
-
- Uma WebUI de operações de AEM que exibe os índices na instância de AEM; facilita a compreensão de quais índices existem; pode ser direcionada ou aumentada.
-
-
Log do Construtor de consultas
DEBUG @ com.day.cq.search.impl.builder.QueryImpl
-
Log de execução de consulta do Oak
DEBUG @ org.apache.jackrabbit.oak.query
-
-
Configurações de OSGi do mecanismo de consulta Apache Jackrabbit
- Configuração OSGi que define o comportamento de falha para consultas de passagem.
- No AEM em /system/console/configMgr#org.apache.jackrabbit.oak.query.QueryEngineSettingsService
-
NodeCounter JMX Mbean
- MBean JMX usado para estimar o número de nós em árvores de conteúdo no AEM.
- No AEM em /system/console/jmx/org.apache.jackrabbit.oak%3Aname%3DnodeCounter%2Ctype%3DNodeCounter
Comunidade suportada community-supported
-
Gerador de Definição de Índice Oak em
https://oakutils.appspot.com/generate/index
- Gerar Índice de Propriedade de Lucência ideal a partir de instruções de consulta XPath ou JCR-SQL2.
-
Plug-in do Chrome para AEM
- O Plug-in do AEM para Chrome é uma extensão de navegador da Web do Google Chrome que expõe dados de log por solicitação, incluindo consultas de execução e seus planos de consulta, no console de ferramentas de desenvolvimento do navegador.
- Exige que você instale e habilite o Rastreador de Log do Sling 1.0.2+ no AEM.