Show Menu
TEMAS×

Resolución de problemas de Consultas lentas

Clasificaciones de Consulta lenta

Existen tres clasificaciones principales de consultas lentas en AEM, enumeradas por gravedad:
  1. consultas sin índice
    • Consultas que no se resuelven en un índice y atraviesan el contenido del JCR para recopilar resultados
  2. consultas poco restringidas (o con ámbito)
    • Consultas que se resuelven en un índice, pero que deben recorrer todas las entradas de índice para recopilar resultados
  3. consultas de conjuntos de resultados grandes
    • Consultas que devuelven un gran número de resultados
Las dos primeras clasificaciones de consultas (sin índice y mal restringidas) son lentas, ya que obligan al motor de consulta Oak a inspeccionar cada resultado potencial (nodo de contenido o entrada de índice) para identificar qué pertenece al conjunto de resultados real .
El acto de inspeccionar cada posible resultado es lo que se conoce como Traversing.
Dado que debe inspeccionarse cada posible resultado, el costo para determinar el resultado real crece de manera lineal con el número de posibles resultados.
Añadir las restricciones de consulta y los índices de ajuste permite almacenar los datos del índice en un formato optimizado que permite una rápida recuperación de los resultados y reduce o elimina la necesidad de realizar una inspección lineal de los posibles conjuntos de resultados.
En AEM 6.3, de forma predeterminada, cuando se alcanza un recorrido de 100.000, la consulta falla y emite una excepción. Este límite no existe de forma predeterminada en las versiones AEM anteriores a AEM 6.3, pero se puede establecer mediante la configuración OSGi de Apache Jackrabbit Engine y el grano JMX QueryEngineSettings (propiedad LimitReads).

Detección de Consultas sin índice

Durante el desarrollo

Explicar todas las consultas y asegurarse de que sus planes de consulta no contengan el /* en ellos se puede encontrar una explicación. Ejemplo de plan de consulta de recorrido:
  • PLAN: [nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */

Post-implementación

  • Monitoree las consultas error.log de recorrido sin índice:
    • *INFO* org.apache.jackrabbit.oak.query.QueryImpl Traversal query (query without index) ... ; consider creating and index
    • Este mensaje solo se registra si no hay ningún índice disponible y si la consulta potencialmente atraviesa muchos nodos. Los mensajes no se registran si hay un índice disponible, pero la cantidad que se va a recorrer es pequeña y, por lo tanto, rápida.
  • Visite la consola de operaciones de rendimiento de Consulta de AEM y Explicar las consultas lentas que buscan explicaciones de consulta de índice o transversales.

Detección de Consultas con restricciones deficientes

Durante el desarrollo

Explicar todas las consultas y asegurarse de que se resuelven en un índice ajustado para coincidir con las restricciones de propiedad de la consulta.
  • La cobertura del plan de consulta ideal tiene indexRules para todas las restricciones de propiedad, y como mínimo para las restricciones de propiedad más estrictas de la consulta.
  • Las Consultas que ordenan los resultados deben resolverse en un índice de propiedades de Lucene con reglas de índice para las propiedades ordenadas por las que se configuran orderable=true.

Por ejemplo, el valor predeterminado cqPageLucene no tiene una regla de índice para jcr:content/cq:tags

Antes de agregar la regla de índice cq:tags
  • cq:regla de índice de etiquetas
    • No existe de forma predeterminada
  • consulta Consulta Builder
    type=cq:Page
    property=jcr:content/cq:tags
    property.value=my:tag
    
    
  • Plan de Consulta
    [cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene) *:* where [a].[jcr:content/cq:tags] = 'my:tag' */
Esta consulta se resuelve en el cqPageLucene índice, pero como no existe ninguna regla de índice de propiedades para jcr:content o cq:tags , cuando se evalúa esta restricción, todos los registros del cqPageLucene índice se comprueban para determinar una coincidencia. Esto significa que si el índice contiene 1 millón cq:Page de nodos, se comprueba 1 millón de registros para determinar el conjunto de resultados.
Después de agregar la regla de índice cq:tags
  • cq:regla de índice de etiquetas
    /oak:index/cqPageLucene/indexRules/cq:Page/properties/cqTags
    @name=jcr:content/cq:tags
    @propertyIndex=true
    
    
  • consulta Consulta Builder
    type=cq:Page
    property=jcr:content/cq:tags
    property.value=myTagNamespace:myTag
    
    
  • Plan de Consulta
    [cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene) jcr:content/cq:tags:my:tag where [a].[jcr:content/cq:tags] = 'my:tag' */
La adición de indexRule para jcr:content/cq:tags en el cqPageLucene índice permite almacenar cq:tags los datos de forma optimizada.
Cuando se realiza una consulta con la jcr:content/cq:tags restricción, el índice puede buscar los resultados por valor. Esto significa que si 100 cq:Page nodos tienen myTagNamespace:myTag como valor, sólo se devuelven esos 100 resultados, y los otros 999.000 se excluyen de las comprobaciones de restricción, lo que mejora el rendimiento en un factor de 10.000.
Por supuesto, las restricciones de consulta adicionales reducen los conjuntos de resultados elegibles y optimizan aún más la optimización de la consulta.
Del mismo modo, sin una regla de índice adicional para la cq:tags propiedad, incluso una consulta de texto completo con una restricción de cq:tags funcionaría mal, ya que los resultados del índice devolverían todas las coincidencias de texto completo. La restricción de las etiquetas cq:se filtraría después.
Otra causa del filtrado posterior al índice son las Listas de Control de acceso, que a menudo se pierden durante el desarrollo. Intente asegurarse de que la consulta no devuelve rutas de acceso inaccesibles para el usuario. Esto generalmente se puede hacer mediante una mejor estructura de contenido y proporcionando una restricción de ruta relevante en la consulta.
Una manera útil de identificar si el índice Lucene devuelve muchos resultados para devolver un subconjunto muy pequeño como resultado de la consulta es habilitar los registros DEBUG org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndex y ver cuántos documentos se cargan desde el índice. El número de resultados finales frente al número de documentos cargados no debería ser desproporcionado. For more information, see Logging .

Post-implementación

  • Monitoree las consultas error.log de recorrido:
    • *WARN* org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor Traversed ### nodes ... consider creating an index or changing the query
  • Visite la consola de operaciones Rendimiento de Consulta de AEM y Explicar consultas lentas que buscan planes de consulta que no resuelvan las restricciones de propiedad de consulta para indexar reglas de propiedad.

Detección de Consultas de conjuntos de resultados grandes

Durante el desarrollo

Establezca umbrales bajos para oak.queryLimitInMemory (p. ej. 10000) y oak.queryLimitReads (p. ej. 5000) y optimice la consulta costosa al visitar una excepción UnsupportedOperationException que dice "La consulta lee más de nodos x...".
Esto ayuda a evitar consultas que requieren muchos recursos (por ejemplo: no está respaldada por ningún índice o está respaldada por un índice de cobertura menos elevado). Por ejemplo, una consulta que lee nodos 1M produciría muchas E/S y tendría un impacto negativo en el rendimiento general de la aplicación. Por lo tanto, cualquier consulta que falle debido a los límites superiores debe analizarse y optimizarse.

Post-implementación

  • Monitoree los registros de consultas que activan el consumo de memoria traversal de nodos grandes o de gran consumo de memoria de pila: "
    • *WARN* ... java.lang.UnsupportedOperationException: The query read or traversed more than 100000 nodes. To avoid affecting other tasks, processing was stopped.
    • Optimice la consulta para reducir el número de nodos a través de los cuales se realiza el desplazamiento
  • Monitoree los registros de consultas que activan el consumo de memoria de gran pila:
    • *WARN* ... java.lang.UnsupportedOperationException: The query read more than 500000 nodes in memory. To avoid running out of memory, processing was stopped
    • Optimice la consulta para reducir el consumo de memoria del montón
Para las versiones de AEM 6.0 a 6.2, puede ajustar el umbral para el recorrido de nodos mediante parámetros JVM en la secuencia de comandos de inicio de AEM para evitar que grandes consultas sobrecarguen el entorno. Los valores recomendados son:
  • -Doak.queryLimitInMemory=500000
  • -Doak.queryLimitReads=100000
En AEM 6.3, los 2 parámetros anteriores están preconfigurados de forma predeterminada y se pueden modificar mediante OSGi QueryEngineSettings.

Ajuste del rendimiento de la Consulta

El lema de la optimización del rendimiento de consulta en AEM es:
"Cuantas más restricciones, mejor".
A continuación se describen los ajustes recomendados para garantizar el rendimiento de la consulta. Ajuste primero la consulta, una actividad menos complicada y, si es necesario, ajuste las definiciones de índice.

Ajuste de la declaración de Consulta

AEM admite los siguientes idiomas de consulta:
  • Query Builder
  • JCR-SQL2
  • XPath
En el siguiente ejemplo se utiliza Consulta Builder ya que es el lenguaje de consulta más común utilizado por los desarrolladores de AEM; sin embargo, los mismos principios se aplican a JCR-SQL2 y XPath.
  1. Añada una restricción nodetype para que la consulta se resuelva en un índice de propiedades Lucene existente.
  • consulta no optimizada
    property=jcr:content/contentType
    property.value=article-page
    
    
  • consulta optimizada
    type=cq:Page
    property=jcr:content/contentType
    property.value=article-page
    
    
    Las Consultas que carecen de una restricción de tipo de nodo obligan a AEM a asumir el nt:base tipo de nodo, que cada nodo de AEM es un subtipo de, lo que resulta en una restricción de tipo de nodo.
    La configuración type=cq:Page restringe esta consulta solo a cq:Page nodos y resuelve la consulta a AEM cqPageLucene, limitando los resultados a un subconjunto de nodos (solo cq:Page nodos) en AEM.
  1. Ajuste la restricción nodetype de la consulta para que la consulta se resuelva en un índice de propiedades Lucene existente.
  • consulta no optimizada
    type=nt:hierarchyNode
    property=jcr:content/contentType
    property.value=article-page
    
    
  • consulta optimizada
    type=cq:Page
    property=jcr:content/contentType
    property.value=article-page
    
    
    nt:hierarchyNode es el tipo de nodo principal de cq:Page , y suponiendo que jcr:content/contentType=article-page se aplique solamente a cq:Page los nodos a través de nuestra aplicación personalizada, esta consulta sólo devolverá cq:Page nodos donde jcr:content/contentType=article-page . Sin embargo, esta es una restricción subóptima porque:
    • Otros nodos heredan de nt:hierarchyNode (p. ej. dam:Asset ) añadiendo innecesariamente al conjunto de posibles resultados.
    • No existe un índice proporcionado por AEM para nt:hierarchyNode , pero sí un índice proporcionado para cq:Page .
    La configuración type=cq:Page restringe esta consulta solo a cq:Page nodos y resuelve la consulta a AEM cqPageLucene, limitando los resultados a un subconjunto de nodos (solo nodos cq:Page) en AEM.
  1. O bien, ajuste las restricciones de propiedad para que la consulta se resuelva en un índice de propiedades existente.
  • consulta no optimizada
    property=jcr:content/contentType
    property.value=article-page
    
    
  • consulta optimizada
    property=jcr:content/sling:resourceType
    property.value=my-site/components/structure/article-page
    
    
    Si se cambia la restricción de propiedad de jcr:content/contentType (un valor personalizado) a la propiedad bien conocida, la consulta sling:resourceType puede resolver en el índice de propiedades slingResourceType que indexa todo el contenido por sling:resourceType .
    Los índices de propiedades (a diferencia de los índices de propiedades de Lucene) se utilizan mejor cuando la consulta no se detecta por nodetype y una única restricción de propiedad domina el conjunto de resultados.
  1. Añada la restricción de ruta más estricta posible para la consulta. Por ejemplo, preferir /content/my-site/us/en por encima /content/my-site o /content/dam por encima / .
  • consulta no optimizada
    type=cq:Page
    path=/content
    property=jcr:content/contentType
    property.value=article-page
    
    
  • consulta optimizada
    type=cq:Page
    path=/content/my-site/us/en
    property=jcr:content/contentType
    property.value=article-page
    
    
    Al aplicar una escala path=/content a la restricción de ruta, path=/content/my-site/us/en los índices pueden reducir el número de entradas de índice que deben inspeccionarse. Cuando la consulta puede restringir la ruta muy bien, más allá de solo /content o /content/dam , asegúrese de que el índice tiene evaluatePathRestrictions=true .
    Tenga en cuenta que el uso evaluatePathRestrictions aumenta el tamaño del índice.
  1. Cuando sea posible, evite las funciones y operaciones de consulta, como: LIKE y fn:XXXX a medida que sus costos se escalan con el número de resultados basados en restricciones.
  • consulta no optimizada
    type=cq:Page
    property=jcr:content/contentType
    property.operation=like
    property.value=%article%
    
    
  • consulta optimizada
    type=cq:Page
    fulltext=article
    fulltext.relPath=jcr:content/contentType
    
    
    La condición LIKE es lenta de evaluar porque no se puede utilizar ningún índice si el texto está inicio con un comodín ("%...'). La condición jcr:contains permite utilizar un índice de texto completo y, por lo tanto, es preferible. Esto requiere que el Índice de propiedades de Lucene resuelto tenga indexRule para jcr:content/contentType con analayzed=true .
    El uso de funciones de consulta como fn:lowercase(..) puede resultar más difícil de optimizar, ya que no hay equivalentes más rápidos (fuera de configuraciones de analizador de índices más complejas y obtrusivas). Lo mejor es identificar otras restricciones de creación de ámbitos para mejorar el rendimiento general de la consulta, lo que requiere que las funciones funcionen en el conjunto más pequeño posible de resultados potenciales.
  1. Este ajuste es específico del Generador de Consultas y no se aplica a JCR-SQL2 o XPath.
    Utilice el valor de Consulta BuilderTotal cuando el conjunto completo de resultados no sea inmediatamente necesario.
    • consulta no optimizada
      type=cq:Page
      path=/content
      
      
    • consulta optimizada
      type=cq:Page
      path=/content
      p.guessTotal=100
      
      
    En los casos en los que la ejecución de la consulta es rápida pero el número de resultados es grande, p. guessTotal es una optimización crítica para las consultas del Generador de Consultas.
    p.guessTotal=100 indica a Consulta Builder que solo recopile los primeros 100 resultados y defina un indicador booleano que indique si existen al menos otros resultados (pero no cuántos más, ya que contar este número sería lento). Esta optimización destaca para los casos de uso de paginación o carga infinita, donde sólo se muestra un subconjunto de resultados de forma incremental.

Ajuste de índice existente

  1. Si la consulta óptima se resuelve en un índice de propiedades, no queda nada por hacer, ya que los índices de propiedades pueden ajustarse de forma mínima.
  2. De lo contrario, la consulta debería resolver en un índice de propiedades de Lucene. Si no se puede resolver ningún índice, vaya a Creación de un nuevo índice.
  3. Si es necesario, convierta la consulta a XPath o JCR-SQL2.
    • consulta Consulta 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 generado a partir de la consulta del Generador de Consultas
      /jcr:root/content/my-site/us/en//element(*, cq:Page)[jcr:content/@contentType = 'article-page'] order by jcr:content/@publishDate descending
      
      
  4. Proporcione el XPath (o JCR-SQL2) al generador de definiciones de índice Oak para generar la definición optimizada del índice de propiedades de Lucene.
    Definición del índice de propiedades de Lucene generada
    - 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. Combine manualmente la definición generada con el Índice de propiedades de Lucene existente de forma aditiva. Tenga cuidado de no eliminar las configuraciones existentes, ya que pueden utilizarse para satisfacer otras consultas.
    1. Busque el índice de propiedades de Lucene existente que cubre cq:Page (mediante el Administrador de índices). En este caso, /oak:index/cqPageLucene .
    2. Identifique el delta de configuración entre la definición de índice optimizada (paso 4) y el índice existente (/oak:index/cqPageLucene), y agregue las configuraciones que faltan del Índice optimizado a la definición de índice existente.
    3. Por AEM Optimizaciones para volver a indexar, se debe actualizar o reindexar en función de si el contenido existente se verá afectado por este cambio de configuración de índice.

Crear un nuevo índice

  1. Compruebe que la consulta no se resuelve en un índice de propiedades de Lucene existente. Si es así, consulte la sección anterior sobre ajuste e índice existente.
  2. Si es necesario, convierta la consulta a XPath o JCR-SQL2.
    • consulta Consulta Builder
      type=myApp:Author
      property=firstName
      property.value=ira
      
      
    • XPath generado a partir de la consulta del Generador de Consultas
      //element(*, myApp:Page)[@firstName = 'ira']
      
      
  3. Proporcione el XPath (o JCR-SQL2) al generador de definiciones de índice Oak para generar la definición optimizada del índice de propiedades de Lucene.
    Definición del índice de propiedades de Lucene generada
    - compatVersion = 2
    - type = "lucene"
    - async = "async"
    - jcr:primaryType = oak:QueryIndexDefinition
        + indexRules
        + myApp:AuthorModel
            + properties
            + firstName
                - name = "firstName"
                - propertyIndex = true
    
    
  4. Implemente la definición generada del índice de propiedades de Lucene.
    Añada la definición XML proporcionada por Oak Index Definition Generator para el nuevo índice al proyecto de AEM que administra las definiciones de índice Oak (recuerde, trate las definiciones de índice Oak como código, ya que el código depende de ellas).
    Implemente y pruebe el nuevo índice siguiendo el ciclo de vida habitual de desarrollo de software de AEM y verifique que la consulta se resuelva en el índice y que la consulta funcione.
    Tras la implementación inicial de este índice, AEM rellenará el índice con los datos necesarios.

¿Cuándo son correctas las consultas sin índice y de recorrido?

Debido a AEM arquitectura de contenido flexible, es difícil predecir y asegurar que las transversales de las estructuras de contenido no evolucionen con el tiempo para ser inaceptablemente grandes.
Por lo tanto, asegúrese de que los índices cumplen las consultas, excepto si la combinación de restricción de ruta y restricción de tipo de nodo garantiza que se recorran menos de 20 nodos.

Herramientas de desarrollo de Consulta

Adobe admitido

  • Consulta Builder Debugger
    • Una WebUI para ejecutar consultas del Generador de Consultas y generar el XPath compatible (para su uso en Explicar Consulta o en el Generador de definiciones de índices Oak).
  • CRXDE Lite - Herramienta Consulta
    • Una WebUI para ejecutar consultas XPath y JCR-SQL2.
    • Ubicado en AEM en /crx/de/index.jsp > Herramientas > Consulta...
    • Un panel de operaciones AEM que proporciona una explicación detallada (plan de Consulta, tiempo de consulta y cantidad de resultados) para cualquier consulta XPATH o JCR-SQL2 dada.
    • Un panel de Operaciones AEM que enumera las consultas lentas y populares recientes ejecutadas en AEM.
    • Una WebUI de operaciones de AEM que muestra los índices en la instancia de AEM; facilita la comprensión de los índices que ya existen, que se pueden segmentar o aumentar.
    • Registro de Consulta Builder
      • DEBUG @ com.day.cq.search.impl.builder.QueryImpl
    • Registro de ejecución de consultas Oak
      • DEBUG @ org.apache.jackrabbit.oak.query
  • Configuración del motor de Consulta Apache Jackrabbit Configuración OSGi
  • NodoContador de granos JMX

Comunidad admitida

    • Genere un índice de propiedades de luminancia óptimo a partir de las sentencias de consulta XPath o JCR-SQL2.
    • Extensión del navegador web de Google Chrome que expone los datos del registro por solicitud, incluidas las consultas ejecutadas y sus planes de consulta, en la consola de herramientas de desarrollo del navegador.
    • Requiere que Sling Log Tracer 1.0.2+ esté instalado y habilitado en AEM.