Det finns tre huvudklassificeringar av långsamma frågor i AEM, ordnade efter allvarlighetsgrad:
Indexlösa frågor
Dåligt begränsade (eller begränsade) frågor
Stora resultatuppsättningsfrågor
De två första klassificeringarna av frågor (indexlösa och dåligt begränsade) är långsamma. De är långsamma eftersom de tvingar Oak-frågemotorn att inspektera varje potentiell resultat (innehållsnod eller indexpost) för att identifiera vilken som tillhör faktisk resultatuppsättning.
Att inspektera varje möjligt resultat kallas att gå igenom.
Eftersom varje potentiellt resultat måste kontrolleras, växer kostnaden för att fastställa det faktiska resultatet linjärt med antalet potentiella resultat.
Genom att lägga till frågebegränsningar och justera index kan indexdata lagras i ett optimerat format som ger snabb resultathämtning och minskar eller eliminerar behovet av linjär kontroll av potentiella resultatuppsättningar.
I AEM 6.3 misslyckas frågan som standard när en genomgång på 100 000 nås och ett undantag genereras. Den här gränsen finns inte som standard i AEM versioner före AEM 6.3, men den kan anges med hjälp av APache Jackrabbit Query Engine Settings OSGi-konfigurationen och QueryEngineSettings JMX-böna (egenskapen LimitReads).
Förklara alla frågor och se till att deras frågeplaner inte innehåller /* bläddra förklaringar i dem. Exempel på genomgång av frågeplan:
[nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */
Övervaka error.log
för indexlösa genomgångsfrågor:
*INFO* org.apache.jackrabbit.oak.query.QueryImpl Traversal query (query without index) ... ; consider creating and index
Besök AEM Frågeprestanda driftskonsol och Förklara långsamma frågor som letar efter stegvis genomgång eller inga indexfrågeförklaringar.
Förklara alla frågor och kontrollera att de matchar ett index som justerats för att matcha frågans egenskapsbegränsningar.
indexRules
för alla egenskapsbegränsningar och minst för de tätaste egenskapsbegränsningarna i frågan.orderable=true.
cqPageLucene
har ingen indexregel för jcr:content/cq:tags
Innan indexregeln cq:tags läggs till
cq:taggindexregel
Fråga i Frågebyggaren
type=cq:Page
property=jcr:content/cq:tags
property.value=my:tag
Frågeplan
[cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene?lang=sv) *:* where [a].[jcr:content/cq:tags] = 'my:tag' */
Den här frågan löses till cqPageLucene
index, men eftersom det inte finns någon egenskapsindexregel för jcr:content
eller cq:tags
, när den här begränsningen utvärderas, alla poster i cqPageLucene
index kontrolleras för att fastställa en matchning. Om indexet innehåller 1 miljon cq:Page
noder kontrolleras sedan 1 miljon poster för att fastställa resultatet.
När indexregeln cq:tags lagts till
cq:taggindexregel
/oak:index/cqPageLucene/indexRules/cq:Page/properties/cqTags
@name=jcr:content/cq:tags
@propertyIndex=true
Fråga i Frågebyggaren
type=cq:Page
property=jcr:content/cq:tags
property.value=myTagNamespace:myTag
Frågeplan
[cq:Page] as [a] /* lucene:cqPageLucene(/oak:index/cqPageLucene?lang=sv) jcr:content/cq:tags:my:tag where [a].[jcr:content/cq:tags] = 'my:tag' */
Tillägget av indexRule för jcr:content/cq:tags
i cqPageLucene
index tillåter cq:tags
data som ska lagras på ett optimerat sätt.
När en fråga med jcr:content/cq:tags
begränsning utförs, indexet kan söka efter resultat efter värde. Det betyder att om 100 cq:Page
noder har myTagNamespace:myTag
som värde returneras endast de 100 resultaten och de andra 999 000 utesluts från begränsningskontrollerna, vilket förbättrar prestandan med en faktor på 10 000.
Fler frågebegränsningar minskar antalet giltiga resultatuppsättningar och optimerar frågeoptimeringen ytterligare.
Utan en extra indexregel för cq:tags
-egenskap, även fulltextfråga med en begränsning för cq:tags
skulle fungera dåligt eftersom resultatet från indexet skulle returnera alla fulltextmatchningar. Begränsningen för cq:tags filtreras efter den.
En annan orsak till postindexfiltrering är Access Control Lists, som ofta missas under utvecklingen. Försök att se till att frågan inte returnerar sökvägar som kanske inte är tillgängliga för användaren. Detta kan göras genom bättre innehållsstruktur och med relevant sökvägsbegränsning för frågan.
Ett praktiskt sätt att identifiera om Lucene-indexet returnerar många resultat för att returnera en liten delmängd som frågeresultat är att aktivera DEBUG-loggar för org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndex
. På så sätt kan du se hur många dokument som läses in från indexet. Antalet slutliga resultat jämfört med antalet inlästa dokument bör inte vara oproportionerligt. Mer information finns i Loggning.
Övervaka error.log
för genomgångsfrågor:
*WARN* org.apache.jackrabbit.oak.spi.query.Cursors$TraversingCursor Traversed ### nodes ... consider creating an index or changing the query
Besök AEM Frågeprestanda driftskonsol och Förklara långsamma frågor som söker efter frågeplaner som inte löser frågeegenskapsbegränsningar till indexegenskapsregler.
Ange låga tröskelvärden för oak.queryLimitInMemory (t.ex. 1000) och oak.queryLimitReads (t.ex. 5000) och optimera den dyra frågan när du klickar på ett UnsupportedOperationException som säger"Frågan läser fler än x noder…".
Genom att ange låga tröskelvärden undviker du resurskrävande frågor (dvs. inte backas upp av något index eller backas upp av mindre täckningsindex). En fråga som till exempel läser en miljon noder skulle leda till mycket IO och negativt påverka programmets prestanda. Alla frågor som inte godkänns på grund av ovanstående gränser bör därför analyseras och optimeras.
Övervaka loggarna för frågor som utlöser genomgång av stora noder eller stor minnesförbrukning i stackar: "
*WARN* ... java.lang.UnsupportedOperationException: The query read or traversed more than 100000 nodes. To avoid affecting other tasks, processing was stopped.
Övervaka loggarna för frågor som utlöser stor minnesförbrukning i stackar:
*WARN* ... java.lang.UnsupportedOperationException: The query read more than 500000 nodes in memory. To avoid running out of memory, processing was stopped
I AEM 6.0-6.2 kan du justera tröskelvärdet för nodgenomgång via JVM-parametrar i AEM startskript för att förhindra att stora frågor överbelastar miljön. Rekommenderade värden är:
-Doak.queryLimitInMemory=500000
-Doak.queryLimitReads=100000
I AEM 6.3 är ovanstående två parametrar förkonfigurerade som standard och kan ändras via OSGi QueryEngineSettings.
Mer information finns under: https://jackrabbit.apache.org/oak/docs/query/query-engine.html#Slow_Queries_and_Read_Limits
Motto för optimering av frågeprestanda i AEM är:
"Ju fler begränsningar, desto bättre."
Följande utkast rekommenderar justeringar för att säkerställa frågeprestanda. Finjustera först frågan, en mindre diskret aktivitet och finjustera sedan indexdefinitionerna om det behövs.
AEM stöder följande frågespråk:
I följande exempel används Query Builder som det vanligaste frågespråket som används av AEM utvecklare, men samma principer gäller för JCR-SQL2 och XPath.
Ooptimerad fråga
property=jcr:content/contentType
property.value=article-page
Optimerad fråga
type=cq:Page
property=jcr:content/contentType
property.value=article-page
Frågor som saknar begränsningskraft för nodetype AEM att anta nt:base
nodetype, som alla noder i AEM är en undertyp till, vilket i sin tur resulterar i ingen nodtypsbegränsning.
Inställning type=cq:Page
begränsar frågan till endast cq:Page
noder och löser frågan till AEM cqPageLucene, vilket begränsar resultatet till en delmängd av noder (endast cq:Page
noder) i AEM.
Ooptimerad fråga
type=nt:hierarchyNode
property=jcr:content/contentType
property.value=article-page
Optimerad fråga
type=cq:Page
property=jcr:content/contentType
property.value=article-page
nt:hierarchyNode
är den överordnade nodtypen för cq:Page
. Anta jcr:content/contentType=article-page
används endast för cq:Page
noder med hjälp av programmet AdobeAnpassad returnerar den här frågan endast cq:Page
noder där jcr:content/contentType=article-page
. Detta flöde är dock en suboptimal begränsning eftersom:
nt:hierarchyNode
(t.ex. dam:Asset
) som lägger till i onödan till de potentiella resultaten.nt:hierarchyNode
, men som det finns ett angivet index för cq:Page
.Inställning type=cq:Page
begränsar frågan till endast cq:Page
noder och löser frågan till AEM cqPageLucene, vilket begränsar resultatet till en delmängd av noder (endast cq:Page-noder) i AEM.
Ooptimerad fråga
property=jcr:content/contentType
property.value=article-page
Optimerad fråga
property=jcr:content/sling:resourceType
property.value=my-site/components/structure/article-page
Ändra egenskapsbegränsningen från jcr:content/contentType
(ett anpassat värde) till den välkända egenskapen sling:resourceType
låter frågan matcha egenskapsindexet slingResourceType
som indexerar allt innehåll med sling:resourceType
.
Egenskapsindex (till skillnad från Lucene-egenskapsindex) används bäst när frågan inte identifieras av nodetype, och en enskild egenskapsbegränsning dominerar resultatuppsättningen.
/content/my-site/us/en
över /content/my-site
, eller /content/dam
över /
.Ooptimerad fråga
type=cq:Page
path=/content
property=jcr:content/contentType
property.value=article-page
Optimerad fråga
type=cq:Page
path=/content/my-site/us/en
property=jcr:content/contentType
property.value=article-page
Omfång för sökvägsbegränsningen från path=/content
till path=/content/my-site/us/en
låter indexen minska antalet indexposter som måste inspekteras. När frågan kan begränsa sökvägen bra, bortom bara /content
eller /content/dam
kontrollerar du att indexet har evaluatePathRestrictions=true
.
Anteckning med evaluatePathRestrictions
ökar indexstorleken.
LIKE
och fn:XXXX
när kostnaderna skalas upp med antalet begränsningsbaserade resultat.Ooptimerad fråga
type=cq:Page
property=jcr:content/contentType
property.operation=like
property.value=%article%
Optimerad fråga
type=cq:Page
fulltext=article
fulltext.relPath=jcr:content/contentType
Villkoret LIKE tar lång tid att utvärdera eftersom inget index kan användas om texten börjar med ett jokertecken ("%…"). jcr:contains-villkoret tillåter att ett fulltextindex används och är därför att föredra. Det matchade Lucene-egenskapsindexet måste ha indexRule för jcr:content/contentType
med analayzed=true
.
Använda frågefunktioner som fn:lowercase(..)
kan vara svårare att optimera eftersom det inte finns snabbare motsvarigheter (utanför mer komplexa och diskreta indexanalysatorkonfigurationer). Det är bäst att identifiera andra omfångsbegränsningar för att förbättra den övergripande frågeprestandan, vilket kräver att funktionerna arbetar på den minsta möjliga uppsättningen möjliga resultat.
Justeringen är Query Builder-specifik och gäller inte JCR-SQL2 eller XPath.
Använd Query Builder' gissningssumma när alla resultat är not omedelbart behövs.
Ooptimerad fråga
type=cq:Page
path=/content
Optimerad fråga
type=cq:Page
path=/content
p.guessTotal=100
Om frågekörningen är snabb men antalet resultat är stort, s. guessTotal
är en viktig optimering för frågor i Query Builder.
p.guessTotal=100
anger för Query Builder att endast samla in de första 100 resultaten. Och om du anger en boolesk flagga som anger om det finns minst ett resultat till (men inte hur många fler, eftersom det blir långsamt om du räknar det här talet). Den här optimeringen är utmärkt för sidnumrering eller oändlig inläsning, där endast en resultatdelmängd visas stegvis.
Om den optimala frågan löses till ett egenskapsindex finns det inget kvar att göra eftersom egenskapsindex är minimalt justeringsbara.
Annars bör frågan matchas mot ett Lucene-egenskapsindex. Om inget index kan tolkas går du till Skapa ett nytt index.
Konvertera frågan till XPath eller JCR-SQL2 efter behov.
Fråga i Frågebyggaren
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 genererad från frågan i Query Builder
/jcr:root/content/my-site/us/en//element(*, cq:Page)[jcr:content/@contentType = 'article-page'] order by jcr:content/@publishDate descending
Ange XPath (eller JCR-SQL2) till Oak Index Definition Generator på https://oakutils.appspot.com/generate/index
så att du kan generera den optimerade definitionen av Lucene-egenskapsindex.
Skapad definition av Lucene-egenskapsindex
- 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"
Sammanfoga manuellt den genererade definitionen i det befintliga Lucene-egenskapsindexet på ett additivt sätt. Var försiktig så att du inte tar bort befintliga konfigurationer eftersom de kan användas för att tillgodose andra frågor.
/oak:index/cqPageLucene
.Kontrollera att frågan inte matchar ett befintligt Lucene-egenskapsindex. Om så är fallet, se avsnittet ovan om justering och befintligt index.
Konvertera frågan till XPath eller JCR-SQL2 efter behov.
Fråga i Frågebyggaren
type=myApp:Author
property=firstName
property.value=ira
XPath genererad från frågan i Query Builder
//element(*, myApp:Page)[@firstName = 'ira']
Ange XPath (eller JCR-SQL2) till Oak Index Definition Generator på https://oakutils.appspot.com/generate/index
så att du kan generera den optimerade definitionen av Lucene-egenskapsindex.
Skapad definition av Lucene-egenskapsindex
- compatVersion = 2
- type = "lucene"
- async = "async"
- jcr:primaryType = oak:QueryIndexDefinition
+ indexRules
+ myApp:AuthorModel
+ properties
+ firstName
- name = "firstName"
- propertyIndex = true
Distribuera den genererade indexdefinitionen för Lucene-egenskap.
Lägg till XML-definitionen från Oak Index Definition Generator för det nya indexet i det AEM projektet som hanterar Oak-indexdefinitioner (kom ihåg att behandla Oak-indexdefinitioner som kod, eftersom koden är beroende av dem).
Distribuera och testa det nya indexet efter den vanliga AEM programutvecklingslivscykeln och kontrollera att frågan löses till indexvärdet och att frågan är korrekt.
Vid den första distributionen av detta index fyller AEM i indexet med nödvändiga data.
På grund av AEM flexibla innehållsarkitekturen är det svårt att förutsäga och se till att genomgången av innehållsstrukturer inte förändras över tid och blir oacceptabla.
Se därför till att index uppfyller frågor, förutom om kombinationen av sökvägsbegränsning och nodetype-begränsning garanterar att färre än 20 noder genomgås någonsin.
Query Builder-felsökning
CRXDE Lite - Frågeverktyg
Loggning i Query Builder
DEBUG @ com.day.cq.search.impl.builder.QueryImpl
Loggning av körning av Oak-frågor
DEBUG @ org.apache.jackrabbit.oak.query
APache Jackrabbit Query Engine Settings OSGi Config
NodeCounter JMX Mbean
Oak Index Definition Generator påhttps://oakutils.appspot.com/generate/index