Detectando Consultas Sem Índice

Durante o desenvolvimento

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:

  • PLANO: [nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */

Pós-implantação

  • 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
    • 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 travamento é pequena e, portanto, rápida.
  • 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.

Detecção de Consultas Mal Restritas

Durante o desenvolvimento

Explicar todas as consultas e garantir que elas sejam 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 restritas no query.
  • Consultas que classificam resultados devem ser resolvidas para um Índice de propriedades do Lucene com regras de índice para as propriedades classificadas por orderable=true.

Por exemplo, o padrão 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

    • Não existe imediatamente
  • Query Builder

    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' */

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

Pós-implantação

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

Detectando Consultas de Conjunto de Resultados Grandes

Durante o desenvolvimento

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.

Pós-implantação

  • 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.
    • Otimizar a consulta para reduzir o número de nós atravessados
  • 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
    • Otimizar a consulta para reduzir o consumo de memória heap

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

Ajuste do desempenho da consulta

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.

Ajustando a Instrução de Consulta

AEM suporta os seguintes idiomas de consulta:

  • Query Builder
  • JCR-SQL2
  • XPath

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.

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

  2. 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:Pagee 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:

    • Outro nó herda de nt:hierarchyNode (por exemplo, dam:Asset) adicionar desnecessariamente ao conjunto de resultados potenciais.
    • Não existe um índice fornecido AEM para 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.

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

  4. Adicione a restrição de caminho mais estrita possível ao query. Por exemplo, preferir /content/my-site/us/en over /content/my-siteou /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=/contentpara 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.

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

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

Ajuste de índice existente

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

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

  3. 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
      
  4. 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"
    
  5. 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.

    1. Localize o Índice de propriedades do Lucene existente que abrange cq:Page (usando o Gerenciador de índices). Nesse caso, /oak:index/cqPageLucene.
    2. Identifique o delta de configuração entre a definição de índice otimizada (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.
    3. De acordo com AEM Práticas recomendadas de reindexação, uma atualização ou reindexação está em ordem, com base em se o conteúdo existente será afetado por essa alteração de configuração de índice.

Criar um novo índice

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

  2. 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']
      
  3. 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
    
  4. 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.

Quando as consultas de índice e travessia estão corretas?

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.

Ferramentas de desenvolvimento de consultas

Adobe Suportado

  • Query Builder Debugger

    • Uma WebUI para executar consultas do Query Builder e gerar o XPath de suporte (para uso em Explain Query ou Oak Index Definition Generator).
    • Localizado em AEM em /libs/cq/search/content/querydebug.html
  • CRXDE Lite - Ferramenta de consulta

    • Uma WebUI para executar consultas XPath e JCR-SQL2.
    • Localizado em AEM em /crx/de/index.jsp > Ferramentas > Consulta…
  • Explicar consulta

    • Um painel de Operações de 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 específica.
  • Consultas lentas/populares

    • Um painel AEM Operations listando as consultas lentas e populares recentes executadas em AEM.
  • Gerenciador de índice

    • Uma WebUI AEM Operations exibindo os índices na instância AEM; facilita a compreensão de quais índices já existem, podem ser direcionados ou aumentados.
  • Logs

    • 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

Comunidade suportada

  • Gerador de definição de índice Oak

    • Gere o índice ideal de propriedades do Lucence a partir das instruções de consulta XPath ou JCR-SQL2.
  • Plug-in do AEM Chrome

    • A extensão do navegador da Web Google Chrome que expõe os dados de log por solicitação, incluindo consultas executadas e seus planos de query, no console de ferramentas dev do navegador.
    • Exige Sling Log Tracer 1.0.2+ para ser instalado e ativado no AEM.

Experience Manager