疑難排解慢速查詢 troubleshooting-slow-queries
查詢分類速度緩慢 slow-query-classifications
AEM中有3個主要的慢速查詢分類,依嚴重性列出:
-
無索引查詢
- 查詢 not 解析為索引並遍歷JCR的內容以收集結果
-
限制不足(或限定範圍)的查詢
- 解析為索引的查詢,但必須遍歷所有索引條目以收集結果
-
大型結果集查詢
- 傳回大量結果的查詢
前2個查詢分類(無索引且限制不良)速度緩慢,因為這會強制Oak查詢引擎檢查每個 潛在 結果(內容節點或索引條目),以標識屬於 實際 結果集。
檢查每個潛在結果的行為稱為「遍歷」。
由於必須檢查每個潛在結果,因此確定實際結果集的成本與電位結果的數目呈線性增長。
添加查詢限制和調整索引允許以優化格式儲存索引資料,提供快速結果檢索,並且減少或消除對潛在結果集的線性檢查的需要。
在AEM 6.3中,依預設,當到達100,000的周遊時,查詢會失敗並擲回例外狀況。 AEM 6.3之前的AEM版本預設不存在此限制,但可透過Apache Jackrabbit查詢引擎設定OSGi設定和QueryEngineSettings JMX Bean(屬性LimitReads)設定。
檢測無索引查詢 detecting-index-less-queries
開發期間 during-development
說明 all 查詢,並確保其查詢計畫不包含 /*橫貫 解釋。 遍歷查詢計畫的示例:
- 計畫:
[nt:unstructured] as [a] /* traverse "/content//*" where ([a].[unindexedProperty] = 'some value') and (isdescendantnode([a], [/content])) */
部署後 post-deployment
檢測限制不良的查詢 detecting-poorly-restricted-queries
開發期間 during-development-1
說明所有查詢,並確保它們解析為符合查詢屬性限制的調整索引。
- 理想的查詢計畫覆蓋範圍
indexRules
,並且至少對於查詢中最緊的屬性限制。 - 對排序結果進行查詢時,應解析為具有按設定的屬性排序的索引規則的Lucene屬性索引
orderable=true.
例如,預設 cqPageLucene
沒有的索引規則 jcr:content/cq:tags
for-example-the-default-cqpagelucene-does-not-have-an-index-rule-for-jcr-content-cq-tags
新增cq:tags索引規則之前
-
cq:tags索引規則
- 不存在
-
查詢產生器查詢
code language-none type=cq:Page property=jcr:content/cq:tags property.value=my:tag
-
查詢計畫
[cq:Page] as [a] /* lucene:cqPageLucene(https://experienceleague.adobe.com/oak:index/cqPageLucene?lang=zh-Hant) *:* where [a].[jcr:content/cq:tags] = 'my:tag' */
此查詢解析到 cqPageLucene
索引,但因為沒有屬性索引規則 jcr:content
或 cq:tags
,在評估此限制時, cqPageLucene
檢查索引以確定匹配項。 這表示如果索引包含100萬 cq:Page
然後檢查100萬條記錄以確定結果集。
新增cq:tags索引規則後
-
cq:tags索引規則
code language-none /oak:index/cqPageLucene/indexRules/cq:Page/properties/cqTags @name=jcr:content/cq:tags @propertyIndex=true
-
查詢產生器查詢
code language-none type=cq:Page property=jcr:content/cq:tags property.value=myTagNamespace:myTag
-
查詢計畫
[cq:Page] as [a] /* lucene:cqPageLucene(https://experienceleague.adobe.com/oak:index/cqPageLucene?lang=zh-Hant) jcr:content/cq:tags:my:tag where [a].[jcr:content/cq:tags] = 'my:tag' */
為 jcr:content/cq:tags
在 cqPageLucene
索引允許 cq:tags
以最佳方式儲存的資料。
若查詢包含 jcr:content/cq:tags
執行限制時,索引可依值查詢結果。 這意味著如果100 cq:Page
節點 myTagNamespace:myTag
作為值,僅返回這100個結果,而其他999,000則從限制檢查中排除,使效能提高10,000倍。
當然,進一步的查詢限制會減少符合條件的結果集,並進一步優化查詢優化。
同樣地,不使用 cq:tags
屬性,甚至具有 cq:tags
執行效果不佳,因為索引的結果會傳回所有全文相符項目。 cq:tags上的限制會在之後篩選。
索引後篩選的另一個原因是存取控制清單,在開發期間經常會遺漏。 嘗試確定查詢未返回用戶可能無法訪問的路徑。 這通常可以透過更好的內容結構以及提供查詢的相關路徑限制來完成。
要識別Lucene索引是否傳回大量結果以傳回非常小的子集(作為查詢結果),有一種很實用的方法是為 org.apache.jackrabbit.oak.plugins.index.lucene.LucenePropertyIndex
並查看從索引中載入的文檔數。 最終結果的數量與載入的文檔的數量之間不應不成比例。 如需詳細資訊,請參閱 記錄.
部署後 post-deployment-1
檢測大型結果集查詢 detecting-large-result-set-queries
開發期間 during-development-2
為oak.queryLimitInMemory設定低臨界值(例如 10000)和oak.queryLimitReads(例如 5000),並在點擊「查詢讀取的節點數超過x個……」的UnsupportedOperationException時,優化昂貴的查詢
這有助於避免資源密集型查詢(即。 不受任何索引的支援或受覆蓋索引較少的支援)。 例如,讀取1M個節點的查詢將導致大量IO,並對整體應用程式效能產生負面影響。 因此,任何因上述限制而失敗的查詢都應加以分析和最佳化。
部署後 post-deployment-2
-
監視日誌中是否有觸發大節點遍歷或大堆記憶體消耗的查詢:
*WARN* ... java.lang.UnsupportedOperationException: The query read or traversed more than 100000 nodes. To avoid affecting other tasks, processing was stopped.
- 優化查詢以減少已遍歷的節點數
-
監視日誌中觸發大堆記憶體消耗的查詢:
*WARN* ... java.lang.UnsupportedOperationException: The query read more than 500000 nodes in memory. To avoid running out of memory, processing was stopped
- 優化查詢以減少堆記憶體消耗
對於AEM 6.0 - 6.2版,您可以透過AEM啟動指令碼中的JVM參數來調整節點周遊臨界值,以防止大型查詢超出環境負載。 建議的值為:
-Doak.queryLimitInMemory=500000
-Doak.queryLimitReads=100000
在AEM 6.3中,上述2個參數預設已預先設定,並可透過OSGi QueryEngineSettings修改。
如需詳細資訊,請參閱: https://jackrabbit.apache.org/oak/docs/query/query-engine.html#Slow_Queries_and_Read_Limits
查詢效能調整 query-performance-tuning
AEM中查詢效能最佳化的格言為:
「限制越多越好。」
以下概述了為確保查詢效能而建議的調整。 首先調整查詢(不那麼引人注目的活動),然後根據需要調整索引定義。
調整查詢語句 adjusting-the-query-statement
AEM支援下列查詢語言:
- 查詢產生器
- JCR-SQL2
- XPath
下列範例使用查詢產生器,因為這是AEM開發人員最常使用的查詢語言,但JCR-SQL2和XPath也適用相同的原則。
-
添加nodetype限制,使查詢解析到現有Lucene屬性索引。
-
未優化的查詢
code language-none property=jcr:content/contentType property.value=article-page
-
最佳化查詢
code language-none type=cq:Page property=jcr:content/contentType property.value=article-page
缺少nodetype限制的查詢會強制AEM採用
nt:base
nodetype,AEM中的每個節點都是的子類型,因此有效地沒有nodetype限制。設定
type=cq:Page
僅限此查詢cq:Page
節點,並將查詢解析為AEM cqPageLucene,將結果限制為節點子集(僅限於cq:Page
節點)。 -
-
調整查詢的nodetype限制,使查詢解析為現有Lucene屬性索引。
-
未優化的查詢
code language-none type=nt:hierarchyNode property=jcr:content/contentType property.value=article-page
-
最佳化查詢
code language-none type=cq:Page property=jcr:content/contentType property.value=article-page
nt:hierarchyNode
是的父節點類型cq:Page
,並假設jcr:content/contentType=article-page
僅套用至cq:Page
透過自訂應用程式傳回的節點,此查詢只會傳回cq:Page
節點jcr:content/contentType=article-page
. 這是次優限制,因為:- 其他節點繼承自
nt:hierarchyNode
(例如dam:Asset
)會不必要地新增至可能的結果集。 - 沒有AEM提供的索引
nt:hierarchyNode
,但由於cq:Page
.
設定
type=cq:Page
僅限此查詢cq:Page
節點,並將查詢解析為AEM cqPageLucene,將結果限制為AEM中的節點子集(僅cq:Page節點)。 -
-
或者,調整屬性限制,使查詢解析為現有的屬性索引。
-
未優化的查詢
code language-none property=jcr:content/contentType property.value=article-page
-
最佳化查詢
code language-none property=jcr:content/sling:resourceType property.value=my-site/components/structure/article-page
將屬性限制從
jcr:content/contentType
(自訂值)至已知屬性sling:resourceType
可讓查詢解析為屬性索引slingResourceType
對所有內容進行索引sling:resourceType
.當查詢不能通過nodetype進行辨識,並且單個屬性限制主導結果集時,最好使用屬性索引(與Lucene屬性索引相對)。
-
-
將最緊的路徑限制添加到查詢。 例如,偏好
/content/my-site/us/en
over/content/my-site
,或/content/dam
over/
.-
未優化的查詢
code language-none type=cq:Page path=/content property=jcr:content/contentType property.value=article-page
-
最佳化查詢
code language-none type=cq:Page path=/content/my-site/us/en property=jcr:content/contentType property.value=article-page
將路徑限制範圍從
path=/content
topath=/content/my-site/us/en
允許索引減少需要檢查的索引條目數。 當查詢可以很好地限制路徑時,/content
或/content/dam
,確保索引具有evaluatePathRestrictions=true
.附註使用
evaluatePathRestrictions
增加索引大小。 -
-
如有可能,請避免查詢函式/操作超調如下:
LIKE
和fn:XXXX
因為其成本隨著限制結果的數量而增加。-
未優化的查詢
code language-none type=cq:Page property=jcr:content/contentType property.operation=like property.value=%article%
-
最佳化查詢
code language-none type=cq:Page fulltext=article fulltext.relPath=jcr:content/contentType
LIKE條件評估速度緩慢,因為如果文字以萬用字元("%。…')開頭,則無法使用索引。 jcr:contains條件允許使用全文索引,因此是推薦條件。 這要求解析的Lucene屬性索引具有的indexRule
jcr:content/contentType
withanalayzed=true
.使用查詢函式,如
fn:lowercase(..)
可能更難進行優化,因為沒有更快的等效值(除了更複雜且更突出的索引分析器配置外)。 最好找出其他範圍界定限制,以改善整體查詢效能,要求函式對盡可能小的潛在結果集進行操作。 -
-
此調整專用於查詢生成器,不適用於JCR-SQL2或XPath。
使用 查詢產生器的guessTotal 當需要完整的結果 時 不立即。
-
未優化的查詢
code language-none type=cq:Page path=/content
-
最佳化查詢
code language-none type=cq:Page path=/content p.guessTotal=100
若是查詢執行速度快但結果數量大的情況,請參閱。
guessTotal
是查詢產生器查詢的重要最佳化。p.guessTotal=100
指示查詢產生器僅收集前100個結果,並設定布林值標幟,指出是否至少存在一個其他結果(但不存在多少個結果),因為計算此數字會導致速度緩慢。 此最佳化優於分頁或無限載入使用案例,其中只會逐步顯示結果的子集。 -
現有索引調整 existing-index-tuning
-
如果最佳查詢解析為屬性索引,則沒有其他任何可做的,因為屬性索引可調性最低。
-
否則,查詢應解析為Lucene屬性索引。 如果無法解析索引,請跳到「建立新索引」。
-
視需要將查詢轉換為XPath或JCR-SQL2。
-
查詢產生器查詢
code language-none 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
code language-none /jcr:root/content/my-site/us/en//element(*, cq:Page)[jcr:content/@contentType = 'article-page'] order by jcr:content/@publishDate descending
-
-
將XPath(或JCR-SQL2)提供給 Oak Index Definition Generator 生成優化的Lucene屬性索引定義。
生成的Lucene屬性索引定義
code language-xml - 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"
-
以添加方式手動將生成的定義合併到現有Lucene屬性索引中。 請小心不要刪除現有配置,因為它們可能用於滿足其他查詢。
- 找出涵蓋cq:Page的現有Lucene屬性索引(使用索引管理器)。 在這種情況下,
/oak:index/cqPageLucene
. - 識別最佳化索引定義(步驟#4)與現有索引(https://experienceleague.adobe.com/oak:index/cqPageLucene?lang=zh-Hant)之間的設定差值,並將最佳化索引中遺漏的設定新增至現有索引定義。
- 根據AEM重新索引最佳實務,會根據現有內容是否會受此索引組態變更影響,依序重新整理或重新索引。
- 找出涵蓋cq:Page的現有Lucene屬性索引(使用索引管理器)。 在這種情況下,
建立新索引 create-a-new-index
-
驗證查詢未解析為現有Lucene屬性索引。 如果有,請參閱上節中關於優化和現有索引的部分。
-
視需要將查詢轉換為XPath或JCR-SQL2。
-
查詢產生器查詢
code language-none type=myApp:Author property=firstName property.value=ira
-
從查詢生成器查詢生成的XPath
code language-none //element(*, myApp:Page)[@firstName = 'ira']
-
-
將XPath(或JCR-SQL2)提供給 Oak Index Definition Generator 生成優化的Lucene屬性索引定義。
生成的Lucene屬性索引定義
code language-xml - compatVersion = 2 - type = "lucene" - async = "async" - jcr:primaryType = oak:QueryIndexDefinition + indexRules + myApp:AuthorModel + properties + firstName - name = "firstName" - propertyIndex = true
-
部署生成的Lucene屬性索引定義。
將Oak Index Definition Generator提供之新索引的XML定義新增至AEM專案,以管理Oak索引定義(請記住,將Oak索引定義視為程式碼,因為程式碼取決於這些定義)。
按照通常的AEM軟體開發生命週期部署並測試新索引,並驗證查詢解析為索引且查詢效能良好。
初始部署此索引後,AEM會將必要資料填入索引。
無索引和遍歷查詢何時可以? when-index-less-and-traversal-queries-are-ok
由於AEM有彈性的內容架構,很難預測並確保內容結構的周遊性不會隨著時間而演變為無法接受的大。
因此,確保索引滿足查詢,除非路徑限制和nodetype限制的組合保證 橫貫的節點不到20個。
查詢開發工具 query-development-tools
Adobe支援 adobe-supported
-
查詢產生器除錯程式
- 執行查詢產生器查詢並產生支援XPath的WebUI(用於說明查詢或Oak索引定義產生器)。
- 位於AEM上: /libs/cq/search/content/querydebug.html
-
CRXDE Lite — 查詢工具
- 用於執行XPath和JCR-SQL2查詢的WebUI。
- 位於AEM上: /crx/de/index.jsp >工具>查詢……
-
- AEM Operations控制面板,提供任何給定XPATH或JCR-SQL2查詢的詳細說明(查詢計畫、查詢時間和結果數)。
-
- AEM Operations控制面板列出最近在AEM上執行的緩慢和熱門查詢。
-
- AEM Operations WebUI顯示AEM例項上的索引;有助於了解哪些索引已經存在,可以定位或增強。
-
-
查詢產生器記錄
DEBUG @ com.day.cq.search.impl.builder.QueryImpl
-
Oak查詢執行記錄
DEBUG @ org.apache.jackrabbit.oak.query
-
-
Apache Jackrabbit查詢引擎設定OSGi設定
- 用於配置遍歷查詢的故障行為的OSGi配置。
- 位於AEM上: /system/console/configMgr#org.apache.jackrabbit.oak.query.QueryEngineSettingsService
-
NodeCounter JMX Mbean
- JMX MBean用於估計AEM中內容樹中的節點數。
- 位於AEM上: /system/console/jmx/org.apache.jackrabbit.oak%3Aname%3DnodeCounter%2Ctype%3DNodeCounter
支援的社群 community-supported
-
Oak Index Definition Generator
- 從XPath或JCR-SQL2查詢語句生成最佳Lucence屬性索引。
-
- Google Chrome網頁瀏覽器擴充功能會在瀏覽器的開發工具主控台中公開每個請求記錄資料,包括已執行的查詢及其查詢計畫。
- 需要 Sling Log Tracer 1.0.2+ 以在AEM上安裝並啟用。