AEM 6.4 chegou ao fim do suporte estendido e esta documentação não é mais atualizada. Para obter mais detalhes, consulte nossa períodos de assistência técnica. Encontre as versões compatíveis here.
Há 3 classificações principais de consultas lentas no AEM, listadas por gravidade:
Consultas sem índice
Consultas restritas incorretamente (ou com escopo)
Grandes consultas de conjunto de resultados
As primeiras 2 classificações de consultas (sem índice e pouco restritas) são lentas, pois forçam o mecanismo de consulta Oak a inspecionar cada potencial resultado (nó de conteúdo ou entrada de índice) para identificar qual pertence ao real conjunto de resultados.
O ato de inspecionar cada resultado potencial é o chamado Traversing.
Uma vez que 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 do índice sejam armazenados em um formato otimizado, permitindo uma recuperação rápida do resultado e reduz ou elimina a necessidade da inspeção linear de conjuntos de resultados potenciais.
No AEM 6.3, por padrão, quando uma travessia de 100.000 é atingida, o query falha e gera 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 das Configurações do mecanismo de consulta Apache Jackrabbit Configuração OSGi e QueryEngineSettings JMX bean (propriedade LimitReads).
Explicar all consultas e garantir que seus planos de query não contenham a variável /* traverse explicação. Exemplo de plano de consulta de percurso:
[nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */
Monitore o error.log
para consultas transversais sem índice:
*INFO* org.apache.jackrabbit.oak.query.QueryImpl Traversal query (query without index) ... ; consider creating and index
Visite o AEM Desempenho da consulta console de operações e Explicar consultas lentas que procuram traversal ou nenhuma explicação de consulta de índice.
Explicar todas as consultas e garantir que elas sejam resolvidas em um índice ajustado para corresponder às restrições de propriedade da consulta.
indexRules
para todas as restrições de propriedade e, no mínimo, para as restrições de propriedade mais restritas no query.orderable=true.
cqPageLucene
não tem uma regra de índice para jcr:content/cq:tags
Antes de adicionar a regra de índice cq:tags
cq:tags Regra de índice
Query Builder
type=cq:Page
property=jcr:content/cq:tags
property.value=my:tag
Plano de consulta
[cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene?lang=pt-BR) *:* where [a].[jcr:content/cq:tags] = 'my:tag' */
Esse query resolve o cqPageLucene
índice, mas porque não existe nenhuma regra de índice de propriedade para jcr:content
ou cq:tags
, quando essa restrição é avaliada, cada registro no cqPageLucene
índice é verificado para determinar uma correspondência. Isso significa que se o índice contiver 1 milhão cq:Page
nós, então 1 milhão de registros são verificados para determinar o conjunto de resultados.
Após adicionar a regra de índice cq:tags
cq:tags Regra de índice
/oak:index/cqPageLucene/indexRules/cq:Page/properties/cqTags
@name=jcr:content/cq:tags
@propertyIndex=true
Query Builder
type=cq:Page
property=jcr:content/cq:tags
property.value=myTagNamespace:myTag
Plano de consulta
[cq:Page] as [a] /* lucene:cqPageLucene(/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 cqPageLucene
o índice permite cq:tags
dados a serem armazenados de forma otimizada.
Quando um query com a variável jcr:content/cq:tags
for executada, o índice poderá procurar resultados por valor. Isso significa que se 100 cq:Page
nós myTagNamespace:myTag
como valor, apenas esses 100 resultados são retornados e os outros 999.000 são excluídos das verificações de restrição, melhorando o desempenho em um fator de 10.000.
É claro que outras restrições de query reduzem os conjuntos de resultados qualificados e otimizam ainda mais a otimização de query.
Da mesma forma, sem uma regra de índice adicional para a variável cq:tags
propriedade, até mesmo uma consulta de texto completo com uma restrição em cq:tags
teria um desempenho ruim, pois os resultados do índice retornariam todas as correspondências de texto completo. A restrição em cq:tags seria filtrada depois.
Outra causa da filtragem pós-índice são as Listas de Controle de Acesso que geralmente são perdidas durante o desenvolvimento. Tente garantir que a consulta não retorne caminhos que possam estar inacessíveis ao usuário. Isso geralmente pode ser feito por uma melhor estrutura de conteúdo, juntamente com a disponibilização de uma restrição de caminho relevante na query.
Uma maneira útil de identificar se o índice Lucene está retornando muitos resultados para retornar um subconjunto muito pequeno como resultado de query é ativar logs DEBUG para org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndex
e veja quantos documentos estão sendo carregados do índice. O número de eventuais resultados versus o número de documentos carregados não deve ser desproporcionado. Para obter mais informações, consulte Registro.
Monitore o error.log
para consultas transversais:
*WARN* org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor Traversed ### nodes ... consider creating an index or changing the query
Visite o AEM Desempenho da consulta console de operações e Explicar consultas lentas que procuram planos de consulta que não resolvem restrições de propriedade de consulta para regras de propriedade de índice.
Defina limites baixos para oak.queryLimitInMemory (por exemplo, 10000) e oak.queryLimitReads (por exemplo, 5000) e otimizar a consulta cara ao hit de um UnsupportedOperationException dizendo "A consulta leu mais de x nós…"
Isso ajuda a evitar consultas que consomem muitos recursos (ou seja, não é suportada por qualquer índice ou pelo índice de cobertura inferior). Por exemplo, uma consulta que lê nós 1M levaria a muitas E/S e afetaria negativamente o desempenho geral do aplicativo. Portanto, qualquer query que falhe devido a limites acima deve ser analisada e otimizada.
Monitore os logs para consultas que acionam grande passagem de nó ou grande consumo de memória heap :
*WARN* ... java.lang.UnsupportedOperationException: The query read or traversed more than 100000 nodes. To avoid affecting other tasks, processing was stopped.
Monitore os logs para consultas que acionam grande consumo de memória heap :
*WARN* ... java.lang.UnsupportedOperationException: The query read more than 500000 nodes in memory. To avoid running out of memory, processing was stopped
Para AEM versões 6.0 - 6.2, você pode ajustar o limite para a travessia do nó por meio de parâmetros da JVM no script de início de AEM para impedir que consultas grandes sobrecarreguem o ambiente. Os valores recomendados são :
-Doak.queryLimitInMemory=500000
-Doak.queryLimitReads=100000
No AEM 6.3, os 2 parâmetros acima são pré-configurados por padrão e podem ser modificados por meio do QueryEngineSettings do OSGi.
Mais informações disponíveis em : https://jackrabbit.apache.org/oak/docs/query/query-engine.html#Slow_Queries_and_Read_Limits
O lema da otimização de desempenho de consulta no AEM é:
"Quanto mais restrições, melhor."
A seguir, são apresentados os ajustes recomendados para garantir o desempenho da consulta. Primeiro ajuste a consulta, uma atividade menos intrusiva e, em seguida, se necessário, ajuste as definições de índice.
AEM suporta os seguintes idiomas de consulta:
O exemplo a seguir usa o Query Builder como a linguagem de consulta mais comum usada por AEM desenvolvedores, no entanto, os mesmos princípios são aplicáveis a JCR-SQL2 e XPath.
Adicione uma restrição do tipo de nó para que a consulta resolva para um Índice de propriedades do Lucene existente.
Consulta não otimizada
property=jcr:content/contentType
property.value=article-page
Consulta otimizada
type=cq:Page
property=jcr:content/contentType
property.value=article-page
Consultas sem uma força de restrição de tipo de nó AEM assumir a variável nt:base
nodetype, que cada nó no AEM é um subtipo de, resultando efetivamente em nenhuma restrição de tipo de nó.
Configuração type=cq:Page
restringe esta consulta somente cq:Page
e resolve a consulta para AEM cqPageLucene, limitando os resultados a um subconjunto de nós (somente cq:Page
nós) em AEM.
Ajuste a restrição do tipo de nó da consulta para que ela seja resolvida para um Índice de propriedades Lucene existente.
Consulta não otimizada
type=nt:hierarchyNode
property=jcr:content/contentType
property.value=article-page
Consulta otimizada
type=cq:Page
property=jcr:content/contentType
property.value=article-page
nt:hierarchyNode
é o tipo de nó principal de cq:Page
e assumindo jcr:content/contentType=article-page
é aplicado somente a cq:Page
nós via nosso aplicativo personalizado, esta consulta retornará somente cq:Page
nós onde jcr:content/contentType=article-page
. No entanto, essa é uma restrição subideal, pois:
nt:hierarchyNode
(por exemplo, dam:Asset
) adicionar desnecessariamente ao conjunto de resultados potenciais.nt:hierarchyNode
, no entanto, como há um índice fornecido para cq:Page
.Configuração type=cq:Page
restringe esta consulta somente cq:Page
e resolve a consulta para AEM cqPageLucene, limitando os resultados a um subconjunto de nós (somente nós cq:Page) em AEM.
Ou ajuste as restrições de propriedade para que a consulta resolva para um Índice de propriedades existente.
Consulta não otimizada
property=jcr:content/contentType
property.value=article-page
Consulta otimizada
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 conhecida sling:resourceType
permite que a query resolva para o índice de propriedade slingResourceType
que indexa todo o conteúdo por sling:resourceType
.
Os índices de propriedade (em vez de Índices de propriedades do Lucene) são melhor usados quando a consulta não é discernível por tipo de nó e uma única restrição de propriedade domina o conjunto de resultados.
Adicione a restrição de caminho mais estrita possível ao query. Por exemplo, preferir /content/my-site/us/en
over /content/my-site
ou /content/dam
over /
.
Consulta não otimizada
type=cq:Page
path=/content
property=jcr:content/contentType
property.value=article-page
Consulta otimizada
type=cq:Page
path=/content/my-site/us/en
property=jcr:content/contentType
property.value=article-page
Escopo da restrição de caminho de path=/content
para path=/content/my-site/us/en
permite que os índices reduzam o número de entradas de índice que precisam ser inspecionadas. Quando a query puder restringir muito bem o caminho, além de apenas /content
ou /content/dam
, assegure-se de que o índice tenha evaluatePathRestrictions=true
.
Observe usando evaluatePathRestrictions
aumenta o tamanho do índice.
Sempre que possível, evite funções/operações de query como: LIKE
e fn:XXXX
dado que os seus custos são proporcionais ao número de resultados baseados em restrições.
Consulta não otimizada
type=cq:Page
property=jcr:content/contentType
property.operation=like
property.value=%article%
Consulta otimizada
type=cq:Page
fulltext=article
fulltext.relPath=jcr:content/contentType
A condição LIKE é lenta para avaliar, pois nenhum índice pode ser usado se o texto começar com um curinga ("%…'). A condição jcr:contains permite usar um índice de texto completo e, portanto, é preferível. Isso requer que o Índice de propriedades do Lucene resolvido tenha indexRule para jcr:content/contentType
com analayzed=true
.
Uso de funções de consulta como fn:lowercase(..)
pode ser mais difícil de otimizar, pois não há equivalentes mais rápidos (fora das configurações mais complexas e discretas 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 potenciais.
Esse ajuste é específico do Query Builder e não se aplica a JCR-SQL2 ou XPath.
Use guessTotal do construtor de consultas quando o conjunto completo de resultados for não imediatamente necessário.
Consulta não otimizada
type=cq:Page
path=/content
Consulta otimizada
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
O é uma otimização crítica para consultas do Query Builder.
p.guessTotal=100
instrui o Query Builder a coletar apenas os primeiros 100 resultados e definir um sinalizador booleano indicando se existem pelo menos mais um resultado (mas não quantos mais, já que a contagem desse número resultaria em lentidão). Essa otimização se sobressai para paginação ou casos de uso de carregamento infinito, onde apenas um subconjunto de resultados é exibido de forma incremental.
Se a consulta ideal for resolvida para um Índice de propriedades, não há mais nada para fazer, pois os Índices de propriedades são minimamente ajustáveis.
Caso contrário, a consulta deve ser resolvida para um Índice de propriedades do Lucene. Se nenhum índice puder ser resolvido, vá para Criação de um novo Índice.
Conforme necessário, converta a consulta para XPath ou JCR-SQL2.
Query Builder
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 da consulta do Query Builder
/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) para Gerador de definição de índice Oak para gerar a definição otimizada do Índice de propriedades do Lucene.
Definição de índice de propriedade do Lucene gerada
- 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 do Lucene existente de forma aditiva. Tenha cuidado para não remover configurações existentes, pois elas podem ser usadas para atender a outros queries.
/oak:index/cqPageLucene
.Verifique se a consulta não resolve um Índice de propriedades do 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.
Query Builder
type=myApp:Author
property=firstName
property.value=ira
XPath gerado da consulta do Query Builder
//element(*, myApp:Page)[@firstName = 'ira']
Forneça o XPath (ou JCR-SQL2) para Gerador de definição de índice Oak para gerar a definição otimizada do Índice de propriedades do Lucene.
Definição de índice de propriedade do Lucene gerada
- 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 propriedades do Lucene gerado.
Adicione a definição XML fornecida pelo Gerador de Definição de Índice Oak para o novo índice ao projeto AEM que gerencia as definições de índice Oak (lembre-se de tratar 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 resolve o índice e se a consulta é executada.
Após a implantação inicial desse índice, o AEM preencherá o índice com os dados necessários.
Devido a AEM arquitetura de conteúdo flexível, é difícil prever e garantir que as travessias das estruturas de conteúdo não evoluam ao longo do tempo para serem inaceitavelmente grandes.
Portanto, verifique se um índice atende a queries, exceto se a combinação de restrição de caminho e restrição de tipo de nó garantir que menos de 20 nós já foram atravessados.
Query Builder Debugger
CRXDE Lite - Ferramenta de consulta
Registro do construtor de consultas
DEBUG @ com.day.cq.search.impl.builder.QueryImpl
Log de execução da consulta Oak
DEBUG @ org.apache.jackrabbit.oak.query
Configuração OSGi das configurações do mecanismo de consulta Apache Jackrabbit
Mbean JMX NodeCounter
Gerador de definição de índice Oak