この記事は、AEM 6 でのインデックス設定について説明しています。クエリおよびインデックス作成のパフォーマンスの最適化のベストプラクティスについては、クエリとインデックスに関するベストプラクティスを参照してください。
Jackrabbit 2 とは異なり、デフォルトでは、Oak はコンテンツのインデックスを作成しません。従来のリレーショナルデータベースと同様に、必要に応じてカスタムインデックスを作成する必要があります。特定のクエリのためのインデックスがない場合は、多数のノードが走査される可能性があります。クエリが機能しても非常に時間がかかる可能性があります。
Oak では、インデックスが使用されないクエリが実行されると、WARN レベルのログメッセージが出力されます。
*WARN* Traversed 1000 nodes with filter Filter(query=select ...) consider creating an index or changing the query
Oak クエリエンジンでは、次の言語がサポートされています。
Apache Oak ベースのバックエンドでは、様々なインデクサーをリポジトリにプラグインすることができます。
インデクサーの 1 つは、プロパティインデックスです。このインデクサーでは、インデックス定義がリポジトリ自体に格納されます。
デフォルトでは、Apache Lucene および Solr の実装も使用できます。どちらもフルテキストのインデックスをサポートしています。
使用できるインデクサーがない場合は、トラバーサルインデックスが使用されます。つまり、コンテンツにインデックスが作成されず、クエリに一致するものを見つけるために、コンテンツノードが走査されます。
あるクエリに対して複数のインデクサーを使用できる場合、使用できる各インデクサーによってクエリ実行コストが見積もられます。次に、見積もりコストが最も低いインデクサーが Oak によって選択されます。
この図は、Apache Oak のクエリ実行メカニズムに関する概要図です。
まず、クエリが抽象構文ツリーへと解析されます。次に、このクエリがチェックされ、Oak クエリのネイティブ言語である SQL-2 に変換されます。
次に、各インデックスが参照されて、クエリのコストが見積もられます。この見積もりが完了すると、最もコストの低いインデックスの結果が取得されます。最後に、その結果がフィルター処理され、現在のユーザーがその結果の読み取りアクセス権を保持していること、およびその結果がクエリ全体に一致していることが確認されます。
大規模なリポジトリでインデックスを構築するには時間がかかります。これは、最初にインデックスを作成するときと、インデックスを再作成(定義を変更した後にインデックスを再構築すること)するときの両方に当てはまります。Oak インデックスのトラブルシューティングと時間のかかるインデックス再作成の防止も参照してください。
非常に大規模なリポジトリでインデックスを再作成する場合、特に MongoDB を使用してフルテキストのインデックスを作成する場合は、事前にテキストを抽出して、oak-run により初期インデックス構築し、インデックスを再作成する方法を検討してください。
インデックスは、リポジトリ内の oak:index ノードの下で、ノードとして設定されます。
インデックスノードのタイプは、oak:QueryIndexDefinition とする必要があります。各インデクサーでは、ノードのプロパティとして複数の設定オプションを使用できます。詳しくは、以下の各インデクサータイプに関する設定の詳細説明を参照してください。
プロパティインデックスは通常、プロパティの制約はあるがフルテキスト検索ではないクエリに適しています。このインデックスを設定するには、次の手順に従います。
http://localhost:4502/crx/de/index.jsp
に移動して CRXDE を開きます。
oak:index の下に新しいノードを作成します。
このノードに PropertyIndex という名前を付け、ノードタイプを oak:QueryIndexDefinition に設定します。
新しいノードに対して次のプロパティを設定します。
property
property(String タイプ)jcr:uuid
(Name タイプ)この例では、jcr:uuid
プロパティに対してインデックスを作成します。このプロパティの役割は、関連付けられたノードの Universally Unique Identifier(UUID)を公開することです。
変更内容を保存します。
プロパティインデックスでは次の設定オプションを使用できます。
type プロパティは、インデックスのタイプを指定するものであり、この例の場合は property に設定する必要があります。
propertyNames プロパティは、インデックスに保存されるプロパティのリストを示します。この例の場合は存在せず、プロパティ名の参照値としてノード名が使用されます。この例では、jcr:uuid プロパティの役割は、インデックスに追加されるノードの一意識別子(UUID)を公開することです。
unique フラグは、true に設定されている場合、プロパティインデックスに対して一意性制約を付加します。
declaringNodeTypes プロパティでは、インデックスが唯一適用される特定のノードタイプを指定できます。
reindex フラグは、true に設定されている場合、コンテンツ全体の再インデックスをトリガーします。
順序付きインデックスはプロパティインデックスの拡張です。ただし、これは廃止されました。このタイプのインデックスは、Lucene プロパティインデックスに置き換える必要があります。
AEM 6 では、Apache Lucene に基づいたフルテキストインデクサーを使用できます。
フルテキストインデックスを設定すると、フルテキスト条件を持つすべてのクエリでフルテキストインデックスが使用されます。インデックスが作成されている他の条件がある場合やパスの制約がある場合でもそのように処理されます。
フルテキストインデックスを設定しないと、フルテキスト条件が設定されたクエリは想定どおりに機能しません。
インデックスは非同期のバックグラウンドスレッドによって更新されるので、一部のフルテキスト検索は、バックグラウンドプロセスが完了するまでの短い期間、使用できない場合があります。
次の手順に従って、Lucene フルテキストインデックスを設定できます。
CRXDE を開き、oak:index の下に新しいノードを作成します。
このノードに LuceneIndex という名前を付け、ノードタイプを oak:QueryIndexDefinition に設定します。
ノードに次のプロパティを追加します。
lucene
(String タイプ)async
(String タイプ)変更内容を保存します。
Lucene インデックスでは次の設定オプションを使用できます。
Oak 1.0.8 以降、Lucene を使用して、フルテキストではないプロパティ制約に関するインデックスを作成できます。
Lucene プロパティインデックスを有効にするには、fulltextEnabled プロパティを必ず false に設定してください。
次のクエリの例について考えてみます。
select * from [nt:base] where [alias] = '/admin'
上記クエリのための Lucene プロパティインデックスを定義するには、oak:index: の下に新しいノードを作成して、次の定義を追加します。
LucenePropertyIndex
oak:QueryIndexDefinition
ノードを作成したら、次のプロパティを追加します。
type:
lucene (of type String)
async:
async (of type String)
fulltextEnabled:
false (of type Boolean)
includePropertyNames: ["alias"] (of type String)
通常のプロパティインデックスと比較して、Lucene プロパティインデックスは常に非同期モードで設定されます。そのため、インデックスから返されるこの結果は、最新のリポジトリ状態を反映していない場合があります。
Lucene プロパティインデックスについて詳しくは、Apache Jackrabbit Oak Lucene ドキュメントのページを参照してください。
Oak ではバージョン 1.2.0 以降、Lucene アナライザーをサポートしています。
アナライザーは、ドキュメントのインデックス作成時とクエリの実行時の両方に使用されます。アナライザーは、フィールドのテキストを調査して、トークンストリームを生成します。Lucene アナライザーは、一連のトークナイザークラスおよびフィルタークラスで構成されています。
このアナライザーは、oak:index
定義内の analyzers
ノード(タイプ nt:unstructured
)を介して定義できます。
インデックスのデフォルトのアナライザーは、analyzers ノードの子の default
に設定されます。
使用可能なアナライザーのリストについては、使用中の Lucene バージョンの API ドキュメントを参照してください。
標準のアナライザーを使用する場合は、次の手順に従って設定できます。
oak:index
ノードの下で、アナライザーで使用するインデックスを見つけます。
このインデックスの下に default
という子ノード(タイプ nt:unstructured
)を作成します。
default ノードに次のプロパティを追加します。
class
String
org.apache.lucene.analysis.standard.StandardAnalyzer
この値は、使用するアナライザークラスの名前です。
また、特定の Lucene バージョンで使用するアナライザーを設定するには、オプションの luceneMatchVersion
プロパティ(string)を使用することもできます。Lucene 4.7 で使用する場合の有効な構文は次のとおりです。
luceneMatchVersion
String
LUCENE_47
luceneMatchVersion
が指定されない場合、Oak では出荷時の Lucene のバージョンが使用されます。
アナライザー設定にストップワードファイルを追加する場合は、default
ノードの下に新しいノードを作成し、次のプロパティを設定します。
stopwords
nt:file
アナライザーは、Tokenizers
、TokenFilters
、および CharFilters
に基づいて構成することもできます。そのためには、アナライザーを指定し、オプションの tokenizer および filtersの子ノードを作成します。これらはリストされた順序で適用されます。https://wiki.apache.org/solr/AnalyzersTokenizersTokenFilters#Specifying_an_Analyzer_in_the_schema を参照してください。
例えば、次のノード構造について考えてみます。
名前: analyzers
名前: default
名前: charFilters
タイプ: nt:unstructured
HTMLStrip
Mapping
名前: tokenizer
プロパティ名: name
String
Standard
名前: filters
タイプ: nt:unstructured
名前: LowerCase
名前: Stop
プロパティ名: words
String
stop1.txt, stop2.txt
名前: stop1.txt
nt:file
名前: stop2.txt
nt:file
filters、charFilters および tokenizers の名前は、ファクトリのサフィックスを削除したものです。つまり、次のようになります。
org.apache.lucene.analysis.standard.StandardTokenizerFactory
が standard
になります
org.apache.lucene.analysis.charfilter.MappingCharFilterFactory
が Mapping
になります
org.apache.lucene.analysis.core.StopFilterFactory
が Stop
になります
ファクトリに必要なすべての設定パラメーターは、対象ノードのプロパティとして指定します。
ストップワードの読み込みなど、外部ファイルのコンテンツを読み込む必要がある場合は、対象ファイル用の子ノード(タイプ nt:file
)を作成することによってコンテンツを指定できます。
Solr インデックスの用途は主にフルテキスト検索ですが、パス、プロパティの制約およびプライマリタイプの制約による検索のインデックス作成にも使用できます。つまり、Oak の Solr インデックスは、あらゆる種類の JCR クエリに使用できます。
AEM での統合はリポジトリレベルで実行されるので、Solr は、Oak(AEM に付属する新しいリポジトリ実装)で使用できるインデックスの候補の 1 つです。
AEM インスタンスでリモートサーバーとして機能するように設定できます。
AEM は、リモート Solr サーバーインスタンスと連動するように設定することもできます。
最新バージョンの Solr をダウンロードして展開します。この方法について詳しくは、Apache Solr のインストールドキュメントを参照してください。
2 つの Solr シャードを作成します。そのためには、Solr の展開先フォルダー内に、各シャード用のフォルダーを作成します。
<solrunpackdirectory>\aemsolr1\node1
<solrunpackdirectory>\aemsolr2\node2
Solr パッケージ内のサンプルインスタンスを探します。通常は、パッケージのルート内の「example
」というフォルダーにあります。
サンプルインスタンスの次のフォルダーを、2 つのシャードフォルダー(aemsolr1\node1
と aemsolr2\node2
)にコピーします。
contexts
etc
lib
resources
scripts
solr-webapp
webapps
start.jar
2 つのシャードフォルダーのそれぞれに、「cfg
」というフォルダーを新規作成します。
新規作成した cfg
フォルダーに、Solr および Zookeeper 設定ファイルを配置します。
Solr および ZooKeeper 設定について詳しくは、Solr の設定に関するドキュメントおよび ZooKeeper 入門ガイドを参照してください。
1 つ目のシャードを ZooKeeper サポート付きで起動するために、aemsolr1\node1
に移動し、次のコマンドを実行します。
java -Xmx2g -Dbootstrap_confdir=./cfg/oak/conf -Dcollection.configName=myconf -DzkRun -DnumShards=2 -jar start.jar
2 つ目のシャードを起動するために、aemsolr2\node2
に移動し、次のコマンドを実行します。
java -Xmx2g -Djetty.port=7574 -DzkHost=localhost:9983 -jar start.jar
両方のシャードが起動したら、Solr インターフェイスに接続し(http://localhost:8983/solr/#/
)、すべてが稼働していることをテストします。
AEM を起動し、次の Web コンソール(http://localhost:4502/system/console/configMgr
)にアクセスします
「Oak Solr remote server configuration」で次の設定を行います。
http://localhost:8983/solr/
「Oak Solr」サーバープロバイダー下のドロップダウンリストで「Remote Solr」を選択します。
CRXDE にアクセスし、Admin でログインします。
solrIndex という新しいノードを oak:index の下に作成し、次のプロパティを設定します。
変更内容を保存します。
以下に、この記事で説明する 3 つの Solr デプロイメントすべてで使用できる基本設定の例を示します。AEM に既に存在する専用プロパティインデックスに対応しているため、他のアプリケーションでは使用しないでください。
この設定を適切に使用するには、アーカイブの内容を直接 Solr ホームディレクトリに配置する必要があります。複数のノードから成るデプロイメントの場合は、各ノードの root フォルダー直下に配置してください。
Solr 推奨設定ファイル
AEM 6.1 では、AEM 6.0 の次の 2 つのインデックス作成ツールが Adobe Consulting Services Commons ツールセットの一部として統合されています。
これらのツールには、AEM ようこそ画面からツール/運営/ダッシュボード/診断を選択してアクセスできます。
これらのツールの使用方法について詳しくは、操作ダッシュボードに関するドキュメントを参照してください。
ACS Commons パッケージは、プロパティインデックスの作成に使用できる OSGi 設定も公開しています。
この設定には、Web コンソールから「Ensure Oak Property Index」を検索してアクセスできます。
クエリの実行が長くかかる場合や、一般的なシステムの応答時間が長くなる場合があります。
ここでは、そのような問題の原因を詳しく追跡するために行う必要のあること、およびその問題の解決策に関する推奨事項を示します。
実行中のクエリについて必要な情報を取得する最も簡単な方法は、クエリの説明を実行ツールを使用することです。このツールを使用すると、ログレベル情報を参照しなくても、処理に時間のかかるクエリのデバッグに必要な正確な情報を収集できます。デバッグ対象となるクエリがわかっている場合は、このツールをお勧めします。
何らかの理由でこのツールを使用できない場合は、インデックスログを単一のファイルで収集し、そのファイルを使用して特定の問題をトラブルシューティングすることができます。
ログを有効にするには、Oak インデックスおよびクエリに関連するカテゴリで DEBUG レベルのログを有効にする必要があります。対象のカテゴリは以下の通りです。
com.day.cq.search カテゴリは、AEM 付属の QueryBuilder ユーティリティを使用している場合にのみ該当します。
トラブルシューティングするクエリを実行している間のみ、ログを DEBUG レベルに設定することが重要です。そうしないと、大量のイベントが長期間ログに出力されます。このため、必要なログを収集したら、前述のカテゴリを INFO レベルのログに戻してください。
次の手順に従って、ログを有効にすることができます。
https://serveraddress:port/system/console/slinglog
を指定します。logs/queryDebug.log
に設定します。この設定によって、すべての DEBUG イベントが 1 つのログファイルに関連付けられます。クエリが評価される方法には、インデックス設定が大きく影響します。分析したり、サポートに送信したりする場合は、インデックス設定を取得することが重要です。設定はコンテンツパッケージとして取得するか、JSON レンディションを取得することができます。
ほとんどの場合、インデックス設定は CRXDE の /oak:index
ノードの下に格納されているので、JSON バージョンは次から取得できます。
https://serveraddress:port/oak:index.tidy.-1.json
インデックスが別の場所で設定されている場合は、その場所に従ってパスを変更してください。
インデックス関連の MBean の出力を取得すると、デバッグに役立つことがあります。手順は次のとおりです。
JMX コンソールに移動します。
https://serveraddress:port/system/console/jmx
次の MBean を検索します。
それぞれの MBean をクリックして、パフォーマンス統計を取得します。サポートへの提出が必要な場合に備え、スクリーンショットを取得するか、記録しておきます。
また、これらの統計に関する JSON 形式の情報を、次の URL で取得できます。
https://serveraddress:port/system/sling/monitoring/mbeans/org/apache/jackrabbit/oak/%2522LuceneIndex%2522.tidy.-1.json
https://serveraddress:port/system/sling/monitoring/mbeans/org/apache/jackrabbit/oak/%2522LuceneIndex%2522.tidy.-1.json
https://serveraddress:port/system/sling/monitoring/mbeans/org/apache/jackrabbit/oak/%2522LuceneIndex%2522.tidy.-1.json
https://serveraddress:port/system/sling/monitoring/mbeans/org/apache/jackrabbit/oak/%2522LuceneIndex%2522.tidy.-1.json
さらに、https://serveraddress:port/system/sling/monitoring/mbeans/org/apache/jackrabbit/oak.tidy.3.json
から、統合された JMX 出力を提供することもできます。これには、Oak 関連のすべての MBean 詳細が JSON 形式で含まれています。
問題のトラブルシューティングのために、次のようなその他の情報を収集できます。
org.apache.jackrabbit.oak-core
バンドルのバージョンをチェックします。https://serveraddress:port/libs/cq/search/content/querydebug.html
からアクセスできます。