在AEM 6中轉換至Oak後,對查詢和索引的管理方式做了一些重大變更。 在Jackrabbit 2下,預設會建立所有內容的索引,並可自由查詢。 在Oak中,必須在oak:index
節點下手動建立索引。 查詢可以在沒有索引的情況下執行,但對於大型資料集,執行速度會非常慢,甚至中止。
本文將概述何時建立索引以及何時不需要索引、避免在不需要查詢時使用查詢的技巧,以及最佳化索引和查詢以盡可能最佳化執行的提示。
此外,請務必閱讀Oak說明檔案,說明如何編寫查詢和索引。 除了索引是AEM 6的新概念外,從舊版AEM安裝移轉程式碼時,Oak查詢中也有語法差異需要考慮。
在設計儲存庫的分類時,需要考慮幾個因素。 其中包括存取控制、本地化、元件和頁面屬性繼承等。
在設計可解決這些問題的分類法時,還必須考慮索引設計的「可通過性」。 在此上下文中,可遍歷性是分類法的能力,它允許根據內容的路徑可預測地訪問內容。 這樣,與需要執行大量查詢的系統相比,更易於維護的系統效能更高。
此外,在設計分類時,務必考慮排序是否重要。 在不需要顯式排序且需要大量同級節點的情況下,最好使用無序節點類型,如sling:Folder
或oak:Unstructured
。 如果需要訂購,則nt:unstructured
和sling:OrderedFolder
更合適。
由於查詢是AEM系統上較耗時的作業之一,因此建議您在元件中避免查詢。 每次呈現頁面時執行多個查詢通常會降低系統的效能。 在呈現元件時,有兩種策略可用來避免執行查詢:遍歷節點和預取結果。
如果儲存庫的設計允許事先知道所需資料的位置,則可從所需路徑中檢索此資料的代碼可以部署,而無需運行查詢以查找該資料。
例如,可轉換符合特定類別的內容。 一種方法是使用類別屬性來組織內容,該類別屬性可以查詢,以填入顯示類別項目的元件。
更好的方法是將此內容按類別結構化,以便手動檢索。
例如,如果內容儲存在類似以下內容的分類中:
/content/myUnstructuredContent/parentCategory/childCategory/contentPiece
/content/myUnstructuredContent/parentCategory/childCategory
節點可以簡單地檢索,其子節點可以被解析並用於渲染元件。
此外,在處理小型或同構結果集時,更快地遍歷儲存庫並收集所需節點,而不是建立一個查詢以返回相同的結果集。 作為一般考慮,應盡可能避免查詢。
有時,元件的內容或要求不允許使用節點遍歷作為檢索所需資料的方法。 在這些情況下,需要在轉換元件之前執行所需的查詢,以確保最終用戶的最佳效能。
如果在編寫元件時可以計算所需的結果,而且內容不會更改,則當作者在對話框中應用設定時可以執行查詢。
如果資料或內容會定期變更,則可依排程或透過監聽程式執行查詢,以更新基礎資料。 然後,結果可以寫入儲存庫中的共用位置。 任何需要此資料的元件,都可從此單一節點提取值,而不需在執行時期執行查詢。
運行未使用索引的查詢時,將記錄有關節點遍歷的警告。 如果此查詢將經常運行,則應建立索引。 要確定給定查詢使用的索引,建議使用解釋查詢工具。 如需詳細資訊,可針對相關搜尋API啟用DEBUG記錄。
修改索引定義後,需要重建索引(重新建立索引)。 根據索引的大小,可能需要一些時間才能完成。
在運行複雜查詢時,可能會將查詢分解為多個較小的查詢,並在事實性更高後通過代碼連接資料。 這些案例的建議是比較兩種方法的績效,以確定哪個選項更適合有關的使用案例。
AEM允許以下列三種方式之一來編寫查詢:
雖然所有查詢在運行前都轉換為SQL2,但查詢轉換的開銷非常小,因此,選擇查詢語言時最關心的是開發團隊的可讀性和舒適性。
使用QueryBuilder時,會依預設判斷結果計數,與舊版Jackrabbit相比,Oak中的結果計數較慢。 要彌補這一缺點,可使用guessTotal參數。
和任何查詢語言一樣,最佳化查詢的第一步是瞭解查詢的執行方式。 要啟用此活動,可以使用「操作儀表板」中的解釋查詢工具。 使用此工具,可插入並解釋查詢。 如果查詢將導致大型儲存庫以及執行時間和將使用的索引出現問題,則會顯示警告。 此工具也可以載入慢速和常用查詢清單,然後加以說明並最佳化。
若要取得有關Oak如何選擇要使用的索引以及查詢引擎如何實際執行查詢的其他資訊,可針對下列封裝新增DEBUG記錄設定:
請務必在查詢除錯完成後移除此記錄器,因為查詢會輸出許多活動,並最終會用記錄檔填滿您的磁碟。
有關如何執行此操作的詳細資訊,請參閱記錄文檔。
Lucene註冊一個JMX Bean,該Bean將提供有關索引內容的詳細資訊,包括每個索引中存在的文檔的大小和數量。
您可以通過訪問https://server:port/system/console/jmx
的JMX控制台訪問它
登錄到JMX控制台後,請搜索Lucene Index Statistics以查找它。 其他索引統計資訊可在IndexStats MBean中找到。
對於查詢統計資訊,請查看名為Oak查詢統計資訊的MBean。
如果您想使用Luke之類的工具來挖掘索引,則需要使用Oak控制台將索引從NodeStore
轉儲到檔案系統目錄。 有關如何執行此操作的說明,請閱讀Lucene文檔。
您也可以擷取系統中的JSON格式索引。 若要這麼做,您必須存取https://server:port/oak:index.tidy.-1.json
開發期間
為oak.queryLimitInMemory
設定低臨界值(例如 10000)和橡樹。 queryLimitReads
(例如5000),並最佳化當點擊「查詢讀取的節點數超過x個……」的UnsupportedOperationException時,昂貴的查詢。
這有助於避免資源密集型查詢(即 不受任何索引的支援,或受較少覆蓋指數的支援)。 例如,讀取100萬個節點的查詢會導致I/O增加,並對整體應用程式效能產生負面影響。 任何因上述限制而失敗的查詢都應加以分析和最佳化。
監視日誌中觸發大節點遍歷或大堆記憶體消耗的查詢:"
*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個參數是預先設定的OOTB,並可透過OSGi QueryEngineSettings持續存在。
以下網址提供更多資訊:https://jackrabbit.apache.org/oak/docs/query/query-engine.html#Slow_Queries_and_Read_Limits
建立或最佳化索引時,首先要問的問題是,是否確實需要索引來設定特定情況。 如果您只要運行問題查詢一次,或僅偶爾運行查詢,並且在通過批處理的非高峰時間運行,則最好不要建立索引。
建立索引後,每次更新索引資料時,索引也必須更新。 由於這對系統具有效能影響,因此僅應在實際需要索引時建立索引。
此外,索引只有在索引中包含的資料足夠唯一以保證其安全時才有用。 考慮一本書中的索引及其涵蓋的主題。 在為文字中的一組主題建立索引時,通常會有數百或數千個項目,這可讓您快速跳至頁面的子集,以快速找到您要尋找的資訊。 如果該索引只有兩三個條目,每個條目指向幾百個頁面,則該索引將不太有用。 這一概念同樣適用於資料庫索引。 如果只有幾個唯一值,則索引將非常有用。 話雖如此,一個指數也可能變得過大,無法發揮作用。 要查看索引統計資訊,請參見上面的索引統計資訊。
Lucene索引已在Oak 1.0.9中引入,並針對AEM 6初次啟動時引入的屬性索引提供一些強大的最佳化功能。 在決定是使用Lucene索引還是屬性索引時,請考慮以下因素:
通常,建議您使用Lucene索引,除非您迫切需要使用屬性索引,以便獲得更高的效能和靈活性。
AEM也依預設提供Solr索引支援。 這主要用於支援全文搜尋,但也可用於支援任何類型的JCR查詢。 當AEM例項沒有CPU容量來處理搜尋密集型部署(例如同時擁有大量使用者的搜尋導向網站)所需查詢數時,應考慮Solr。 此外,Solr可以採用基於爬蟲的方法來實現,以利用平台的一些更高級的功能。
Solr索引可設定為在AEM伺服器上執行以用於開發環境,或可卸載至遠端例項,以改善生產與測試環境的搜尋延展性。 雖然卸載搜索將改善可擴充性,但會引入延遲,因此,除非需要,否則不建議這樣做。 有關如何配置Solr整合以及如何建立Solr索引的詳細資訊,請參閱Oak查詢和索引文檔。
採用整合的Solr搜索方法時,可以將索引卸載到Solr伺服器。 如果通過基於爬蟲的方法使用Solr伺服器的更高級功能,則需要額外的配置工作。 Headwire已建立開放源碼連接器以加速這些類型的實施。
採用此方法的缺點是,雖然依預設,AEM查詢會尊重ACL,因此會隱藏使用者無權存取的結果,將搜尋外部化至Solr伺服器將不支援此功能。 如果要以這種方式將搜尋外部化,則必須格外小心,以確保使用者不會看到他們不應看到的結果。
如果此方法可能適合的潛在使用案例,則可能需要匯整來自多個來源的搜尋資料。 例如,您可能有一個網站是在AEM上代管,而另一個網站是在第三方平台上代管。 Solr可設定為編目兩個網站的內容,並將它們儲存在匯總索引中。 這可允許跨網站搜尋。
Oak documentation for Lucene indexes列出了設計索引時要考慮的幾個事項:
如果查詢使用不同的路徑限制,請使用evaluatePathRestrictions
。 這將允許查詢返回指定路徑下的結果子集,然後根據查詢篩選結果。 否則,查詢將搜索與儲存庫中的查詢參數匹配的所有結果,然後根據路徑進行篩選。
如果查詢使用排序,請為sorted屬性定義明確的屬性,並為其設定ordered
至true
。 這樣,結果就可以在索引中按此順序排列,並節省查詢執行時的昂貴排序操作。
只將所需內容放入索引中。 新增不需要的功能或屬性會導致索引增長並降低效能。
在屬性索引中,具有唯一的屬性名稱有助於減小索引的大小,但對於Lucene索引,應使用nodeTypes
和mixins
來實現連貫索引。 查詢特定的nodeType
或mixin
將比查詢nt:base
更有效。 使用此方法時,請為相關的nodeTypes
定義indexRules
。
如果您的查詢僅在某些路徑下運行,請在這些路徑下建立這些索引。 索引在儲存庫的根目錄中不是必需的。
建議在所有要索引的屬性都相關時使用單一索引,讓Lucene能夠以原生方式評估盡可能多的屬性限制。 此外,查詢將只使用一個索引,即使在執行連接時也是如此。
在遠程儲存NodeStore
時,可以啟用名為CopyOnRead
的選項。 該選項將使遠程索引在讀取時寫入本地檔案系統。 這有助於改進經常針對這些遠程索引運行的查詢的效能。
這可在OSGi控制台的LuceneIndexProvider服務下進行設定,並自Oak 1.0.13起預設啟用。
刪除索引時,建議您先將type
屬性設為disabled
來暫時停用索引,然後進行測試,以確保應用程式在實際刪除前正常運作。 請注意,索引在停用時不會更新,因此,如果重新啟用索引,並且可能需要重新建立索引,則可能沒有正確的內容。
在刪除TarMK實例上的屬性索引後,將需要運行壓縮以回收任何正在使用的磁碟空間。 對於Lucene索引,實際索引內容存在於BlobStore中,因此需要資料存放區廢棄項目收集。
刪除MongoDB實例上的索引時,刪除成本與索引中的節點數成比例。 由於刪除大型索引可能會造成問題,建議的方法是使用例如oak-mongo.js的工具,停用索引並僅在維護視窗中刪除它。 請注意,此方法不適用於一般節點內容,因為它可能會造成資料不一致。
如需oak-mongo.js的詳細資訊,請參閱Oak檔案的命令列工具區段。
本節概述only重新索引Oak索引的可接受理由。
在下列原因外,開始Oak索引的重新索引將not變更行為或解決問題,並無須增加AEM的負載。
除非下表中的原因涵蓋,否則應避免重新索引Oak索引。
在查閱下表以判斷是否重新建立索引之前,請務必**確認:
唯一可接受的Oak索引重新索引的非重新索引條件,是Oak索引的組態已變更。
應始終對重新索引進行處理,並適當考慮它對AEM整體效能的影響,並在活動量較低或維護期間執行。
以下是可能的細節問題和決議:
適用/如果:
症狀:
如何驗證:
jcr:created
或jcr:lastModified
屬性如何解決:
盧塞 內指數
或者,對缺少的節點進行觸摸(執行良性寫操作)
適用/如果:
症狀:
如何驗證:
diffStoredIndexDefinition
更改了索引定義。如何解決:
下表說明重新建立Oak索引索引將解決此問題的唯一可接受的錯誤和例外情況。
如果AEM發生不符合下列標準的問題,請執行not重新索引任何索引,因為它不會解決問題。
以下是可能的細節問題和決議:
適用/如果:
症狀:
如何驗證:
如何解決:
執行遍歷儲存庫檢查;例如:
http://localhost:4502/system/console/repositorycheck
遍歷儲存庫可確定是否缺少其他二進位檔案(除lucene檔案外)
如果缺少lucene索引以外的二進位檔案,則從備份中恢復
否則,re-index all lucene索引
注意:
此條件表示可能導致ANY二進位的配置錯誤的資料儲存(如 資產二進位檔)遺失。
在這種情況下,恢復到儲存庫的最後一個已知正常版本,以恢復所有丟失的二進位檔案。
適用/如果:
症狀:
如何驗證:
AsyncIndexUpdate
(每5秒)將失敗,錯誤。log中出現例外:
...a Lucene index file is corrupt...
如何解決:
在AEM 6.4中,oak-run.jar是ONLY支援的方法,可在MongoMK或RDBMK儲存庫上重新建立索引。
使用oak-run.jar重新索引屬性索引
在屬性索引上將async-reindex屬性設為true
[oak:queryIndexDefinition]@reindex-async=true
使用Web控制台,透過PropertyIndexAsyncReindex MBean重新索引屬性索引;
例如,
使用oak-run.jar重新索引 Lucene屬性索引。
在lucene屬性索引上將async-reindex屬性設為true
[oak:queryIndexDefinition]@reindex-async=true
上節摘要並框定AEM內容中Apache Oak檔案中的Oak重新索引指引。
文字預擷取是從二進位檔擷取和處理文字的程式,直接透過隔離的程式從資料存放區擷取並處理文字,並直接將擷取的文字呈現在Oak索引的後續重新/索引中。
/oak:index/damAssetLucene
。啟用二進位擷取的重新索引existing lucene索引
支援在啟用二進位擷取的情況下,將new lucene索引部署至AEM
文本預抽取不能用於添加到儲存庫的新內容,也不必。
將新內容添加到儲存庫中,將通過非同步全文索引過程自然地逐步編製索引(預設情況下,每5秒)。
在AEM的正常運作下,例如透過網頁UI上傳資產或程式化收錄資產,AEM將自動以增量式全文索引新的二進位內容。 由於資料量是遞增的,而且相對較小(大約5秒內可保存至儲存庫的資料量),AEM可在建立索引期間從二進位檔案執行全文擷取,而不會影響整體系統效能。
您將重新索引執行全文二進位擷取的lucene索引,或部署新索引,將現有內容的全文索引二進位檔案
要預先提取文本的內容(二進位檔案)必須位於儲存庫中
用於生成CSV檔案並執行最終重新索引的維護窗口
Oak版本:1.0.18+、1.2.3+
oak-run.jarversion 1.7.4+
檔案系統資料夾/共用,以儲存可從索引AEM例項存取的擷取文字
以下概述的oak-run.jar命令可在https://jackrabbit.apache.org/oak/docs/query/pre-extract-text.html上完整列舉 。
上圖和以下步驟可說明並補充Apache Oak檔案中概述的技術文字預先擷取步驟。
產生要預先擷取的內容清單
在維護窗口/低使用期間執行步驟1(a-b),因為在此操作期間會遍歷節點儲存,這可能會對系統產生大量負載。
1a。 執行oak-run.jar --generate
以建立預提取其文本的節點清單。
1b. 節點清單(1a)以CSV檔案形式儲存到檔案系統
請注意,每次執行--generate
時,都會遍歷整個節點儲存(如oak-run命令中的路徑所指定),並建立new CSV檔案。 CSV檔案是not,在文本預提取過程的離散執行之間重新使用(步驟1 - 2)。
預先擷取文字至檔案系統
步驟2(a-c)只能與資料存放區互動,才可在AEM的正常運作期間執行。
2a。 執行oak-run.jar --tika
以預先擷取(1b)中產生之CSV檔案中列舉之二進位節點的文字
2b. 在(2a)中啟動的程式會直接存取在資料存放區的CSV中定義的二進位節點,並擷取文字。
2c. 提取的文本以Oak重新索引過程(3a)可接收的格式儲存在檔案系統上
預先提取的文本在CSV中由二進位指紋標識。 如果二進位檔案相同,則可在AEM執行個體中使用相同的預先擷取文字。 由於AEM Publish通常是AEM Author的子集,因此從AEM Author預先擷取的文字通常也可用來重新為AEM Publish建立索引(假設AEM Publish具備擷取文字檔案的檔案系統存取權)。
預先擷取的文字可逐漸新增至一段時間。 文字預擷取將略過先前擷取的二進位檔的擷取,因此最好保留預先擷取的文字,以免日後必須重新索引(假設擷取的內容不會過大)。 如果是,請評估在中間壓縮內容,因為文字會很好壓縮)。
重新為Oak索引建立索引,從擷取的文字檔案擷取全文
在維護/低使用期間執行重新索引(步驟3a-b),因為在此操作期間會遍歷節點儲存,這可能會對系統造成大量負載。
3a。 在AEM中 調用Lucene索引的重新索引
3b. Apache Jackrabbit Oak DataStore PreExtractedTextProvider OSGi組態(設定為透過檔案系統路徑指向Extracted文字)會指示Oak從Extracted Files取得全文,並避免直接點擊和處理儲存在儲存庫中的資料。