AEM 6.4 ha llegado al final de la compatibilidad ampliada y esta documentación ya no se actualiza. Para obtener más información, consulte nuestra períodos de asistencia técnica. Buscar las versiones compatibles here.
Existen tres clasificaciones principales de consultas lentas en AEM, enumeradas por gravedad:
Consultas sin índice
Consultas poco restringidas (o con ámbitos)
Consultas de conjuntos de resultados grandes
Las dos primeras clasificaciones de consultas (sin índice y mal restringidas) son lentas, ya que obligan al motor de consultas Oak a inspeccionar cada una potencial resultado (nodo de contenido o entrada de índice) para identificar qué pertenece a la variable real conjunto de resultados.
El acto de inspeccionar cada posible resultado es lo que se conoce como Traversing.
Dado que es necesario inspeccionar cada posible resultado, el costo para determinar el conjunto de resultados real aumenta linealmente con el número de posibles resultados.
La adición de restricciones de consulta e índices de ajuste permite almacenar los datos de índice en un formato optimizado que permite una rápida recuperación de resultados y, además, reduce o elimina la necesidad de la inspección lineal de posibles conjuntos de resultados.
En AEM 6.3, de forma predeterminada, cuando se alcanza una travesía de 100 000, la consulta falla y genera una excepción. Este límite no existe de forma predeterminada en versiones AEM anteriores a la AEM 6.3, pero se puede establecer a través de la configuración OSGi de Apache Jackrabbit Query Engine y QueryEngineSettings JMX bean (propiedad LimitReads).
Explicar all las consultas y asegúrese de que sus planes de consulta no contienen la variable /* traverse en ellos. Ejemplo de plan de consulta de recorrido:
[nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */
Monitorice el error.log
para consultas transversales sin índice:
*INFO* org.apache.jackrabbit.oak.query.QueryImpl Traversal query (query without index) ... ; consider creating and index
Visite la AEM Rendimiento de la consulta consola operaciones y Explicar consultas lentas que buscan explicaciones de consulta transversal o sin índice.
Explique todas las consultas y asegúrese de que se resuelven en un índice ajustado para coincidir con las restricciones de propiedad de la consulta.
indexRules
para todas las restricciones de propiedad y como mínimo para las restricciones de propiedad más estrictas de la consulta.orderable=true.
cqPageLucene
no tiene una regla de índice para jcr:content/cq:tags
Antes de añadir la regla de índice cq:tags
cq:tags Regla de índice
Consulta del generador de consultas
type=cq:Page
property=jcr:content/cq:tags
property.value=my:tag
Plan de consulta
[cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene?lang=es) *:* where [a].[jcr:content/cq:tags] = 'my:tag' */
Esta consulta se resuelve en el cqPageLucene
index, pero porque no existe ninguna regla de índice de propiedad para jcr:content
o cq:tags
, cuando se evalúa esta restricción, todos los registros de la variable cqPageLucene
se comprueba el índice para determinar una coincidencia. Esto significa que si el índice contiene 1 millón cq:Page
, se comprueban 1 millón de registros para determinar el conjunto de resultados.
Después de añadir la regla de índice cq:tags
cq:tags Regla de índice
/oak:index/cqPageLucene/indexRules/cq:Page/properties/cqTags
@name=jcr:content/cq:tags
@propertyIndex=true
Consulta del generador de consultas
type=cq:Page
property=jcr:content/cq:tags
property.value=myTagNamespace:myTag
Plan de consulta
[cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene?lang=es) 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
index permite cq:tags
datos que se van a almacenar de forma optimizada.
Cuando una consulta con la variable jcr:content/cq:tags
la restricción se realiza, el índice puede buscar los resultados por valor. Eso significa que si 100 cq:Page
los nodos tienen myTagNamespace:myTag
como valor, sólo se devuelven esos 100 resultados y los otros 999.000 se excluyen de las comprobaciones de restricciones, lo que mejora el rendimiento en un factor de 10.000.
Por supuesto, las restricciones de consulta adicionales reducen los conjuntos de resultados aptos y optimizan aún más la optimización de la consulta.
Del mismo modo, sin una regla de índice adicional para la variable cq:tags
, incluso una consulta de texto completo con una restricción de cq:tags
tendría un rendimiento pobre, ya que los resultados del índice devolverían todas las coincidencias de texto completo. La restricción en cq:tags se filtraría después de ella.
Otra causa del filtrado posterior al índice es las Listas de control de acceso, que a menudo se pierden durante el desarrollo. Intente asegurarse de que la consulta no devuelva rutas que podrían no ser accesibles para el usuario. Esto generalmente se puede hacer mejorando la estructura de contenido junto con proporcionando una restricción de ruta relevante en la consulta.
Una forma útil de identificar si el índice de Lucene devuelve muchos resultados para devolver un subconjunto muy pequeño como resultado de la consulta es habilitar los registros de DEBUG para org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndex
y ver cuántos documentos se están cargando desde el índice. El número de resultados finales frente al número de documentos cargados no debería ser desproporcionado. Para obtener más información, consulte Registro.
Monitorice el error.log
para consultas transversales:
*WARN* org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor Traversed ### nodes ... consider creating an index or changing the query
Visite la AEM Rendimiento de la consulta consola operaciones y Explicar consultas lentas que buscan planes de consulta que no resuelvan restricciones de propiedad de consulta a reglas de propiedad de índice.
Establezca umbrales bajos para oak.queryLimitInMemory (p. ej. 10000) y oak.queryLimitReads (p. ej. 5000) y optimice la costosa consulta al visitar una excepción UnsupportedOperationException que dice "La consulta lee más de x nodos…".
Esto ayuda a evitar consultas intensivas en recursos (por ejemplo, no está respaldado por ningún índice o está respaldado por un índice menos abarcador). Por ejemplo, una consulta que lee nodos 1M produciría muchas IO y tendría un impacto negativo en el rendimiento general de la aplicación. Por lo tanto, cualquier consulta que falle debido a límites superiores debe analizarse y optimizarse.
Monitorice los registros para las consultas que activan el consumo de memoria de gran nodo transversal o de gran pila:
*WARN* ... java.lang.UnsupportedOperationException: The query read or traversed more than 100000 nodes. To avoid affecting other tasks, processing was stopped.
Monitorice los registros de las consultas que activan el consumo de memoria de pila grande :
*WARN* ... java.lang.UnsupportedOperationException: The query read more than 500000 nodes in memory. To avoid running out of memory, processing was stopped
Para AEM versiones 6.0 - 6.2, puede ajustar el umbral para la travesía de nodos a través de parámetros JVM en el script de inicio de AEM para evitar que las consultas grandes 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 a través de OSGi QueryEngineSettings.
Más información disponible en : https://jackrabbit.apache.org/oak/docs/query/query-engine.html#Slow_Queries_and_Read_Limits
El lema de la optimización del rendimiento de las consultas en AEM es:
"Cuantas más restricciones, mejor".
A continuación se describen los ajustes recomendados para garantizar el rendimiento de las consultas. Ajuste primero la consulta, una actividad menos intrusiva y, si es necesario, ajuste las definiciones de índice.
AEM admite los siguientes idiomas de consulta:
El siguiente ejemplo utiliza Query 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.
Agregue una restricción nodetype para que la consulta se resuelva en un índice de propiedades de 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 no tienen una restricción de tipo de nodo obligan a AEM a asumir la nt:base
nodetype, que cada nodo de AEM es un subtipo de , lo que no produce ninguna restricción de tipo de nodo.
Configuración type=cq:Page
restringe esta consulta solo a cq:Page
y resuelve la consulta en AEM cqPageLucene, limitando los resultados a un subconjunto de nodos (solo cq:Page
nodos) en AEM.
Ajuste la restricción de tipo de nodo de la consulta para que la consulta se resuelva en un índice de propiedades de 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 nodo principal de cq:Page
y suponiendo jcr:content/contentType=article-page
solo se aplica a cq:Page
nodos a través de nuestra aplicación personalizada, esta consulta solo devolverá cq:Page
nodos donde jcr:content/contentType=article-page
. Sin embargo, esta es una restricción subóptima porque:
nt:hierarchyNode
(p. ej. dam:Asset
) añadiendo innecesariamente al conjunto de posibles resultados.nt:hierarchyNode
, sin embargo, ya que hay un índice proporcionado para cq:Page
.Configuración type=cq:Page
restringe esta consulta solo a cq:Page
y resuelve la consulta en AEM cqPageLucene, limitando los resultados a un subconjunto de nodos (solo nodos cq:Page) en AEM.
O bien, ajuste las restricciones de propiedad para que la consulta se resuelva en un índice de propiedad 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
Cambio de la restricción de propiedad de jcr:content/contentType
(un valor personalizado) a la propiedad conocida sling:resourceType
permite que la consulta se resuelva en el índice de propiedad 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 distingue por tipo de nodo y una sola restricción de propiedad domina el conjunto de resultados.
Agregue la restricción de ruta más estricta posible a la consulta. Por ejemplo, prefiera /content/my-site/us/en
over /content/my-site
o /content/dam
over /
.
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
Creación de ámbitos de la restricción de rutas desde path=/content
a path=/content/my-site/us/en
permite que los índices reduzcan el número de entradas de índice que deben inspeccionarse. Cuando la consulta puede restringir la ruta muy bien, más allá de /content
o /content/dam
, asegúrese de que el índice tiene evaluatePathRestrictions=true
.
Tenga en cuenta que evaluatePathRestrictions
aumenta el tamaño del índice.
Cuando sea posible, evite funciones/operaciones de consulta como: LIKE
y fn:XXXX
a medida que sus costes 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 usar ningún índice si el texto comienza con un comodín ("%…"). La condición jcr:contains permite usar un índice de texto completo, y por lo tanto se prefiere. Esto requiere que el índice de propiedades de Lucene resuelto tenga indexRule para jcr:content/contentType
con analayzed=true
.
Uso de funciones de consulta como fn:lowercase(..)
puede ser 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). Es mejor identificar otras restricciones de alcance para mejorar el rendimiento general de la consulta, lo que requiere que las funciones funcionen en el conjunto más pequeño de posibles resultados posibles.
Este ajuste es específico de Query Builder y no se aplica a JCR-SQL2 o XPath.
Uso Adivinación del Generador de consultas cuando el conjunto completo de resultados es no necesario inmediatamente.
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 sea rápida pero el número de resultados sea grande, p. guessTotal
es una optimización crítica para las consultas de Query Builder.
p.guessTotal=100
indica a Query Builder que solo recopile los primeros 100 resultados y establezca un indicador booleano que indique si existen al menos uno más resultados (pero no cuántos más, ya que contar este número resultaría en lentitud). Esta optimización destaca para casos de uso de paginación o carga infinita, donde solo se muestra un subconjunto de resultados de forma incremental.
Si la consulta óptima se resuelve en un índice de propiedades, no queda nada que hacer, ya que los índices de propiedades se pueden ajustar mínimamente.
De lo contrario, la consulta debe resolverse en un índice de propiedades de Lucene. Si no se puede resolver ningún índice, vaya a Creación de un nuevo índice.
Si es necesario, convierta la consulta a XPath o JCR-SQL2.
Consulta del generador de consultas
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 de Query Builder
/jcr:root/content/my-site/us/en//element(*, cq:Page)[jcr:content/@contentType = 'article-page'] order by jcr:content/@publishDate descending
Proporcione XPath (o JCR-SQL2) para Generador de definiciones de índices Oak para generar la definición optimizada del índice de propiedades de Lucene.
Definición del índice de propiedades de Lucene generado
- 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"
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.
/oak:index/cqPageLucene
.Compruebe que la consulta no se resuelva en un índice de propiedades de Lucene existente. Si es así, consulte la sección anterior sobre ajuste e índice existente.
Si es necesario, convierta la consulta a XPath o JCR-SQL2.
Consulta del generador de consultas
type=myApp:Author
property=firstName
property.value=ira
XPath generado a partir de la consulta de Query Builder
//element(*, myApp:Page)[@firstName = 'ira']
Proporcione XPath (o JCR-SQL2) para Generador de definiciones de índices Oak para generar la definición optimizada del índice de propiedades de Lucene.
Definición del índice de propiedades de Lucene generado
- compatVersion = 2
- type = "lucene"
- async = "async"
- jcr:primaryType = oak:QueryIndexDefinition
+ indexRules
+ myApp:AuthorModel
+ properties
+ firstName
- name = "firstName"
- propertyIndex = true
Implemente la definición generada del índice de propiedades de Lucene.
Agregue la definición XML proporcionada por Oak Index Definition Generator para el nuevo índice al proyecto 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 se realice.
Tras la implementación inicial de este índice, AEM rellenará el índice con los datos necesarios.
Debido a AEM arquitectura de contenido flexible, es difícil predecir y garantizar que los cambios en las estructuras de contenido no evolucionen con el tiempo para ser inaceptablemente grandes.
Por lo tanto, asegúrese de que los índices satisfacen las consultas, excepto si la combinación de restricción de ruta y restricción de tipo de nodo garantiza que se atraviesan menos de 20 nodos.
Depurador del generador de consultas
CRXDE Lite - Herramienta Consulta
Registro de Query Builder
DEBUG @ com.day.cq.search.impl.builder.QueryImpl
Registro de ejecución de consultas Oak
DEBUG @ org.apache.jackrabbit.oak.query
Configuración OSGi de Apache Jackrabbit Query Engine
Mbean de NodeCounter JMX
Generador de definiciones de índices Oak