クエリとインデックスに関するベストプラクティス best-practices-for-queries-and-indexing

AEM 6 での Oak への移行に伴い、クエリとインデックスの管理方法に関して大きな変更がいくつか導入されました。Jackrabbit 2 では、デフォルトですべてのコンテンツのインデックスが作成され、自由にクエリを実行できました。Oak では、oak:index ノードの下にインデックスを手動で作成する必要があります。クエリはインデックスなしでも実行できますが、大規模なデータセットの場合は、実行が非常に遅くなるだけでなく、中止されることもあります。

この記事では、インデックスを作成するべき場合とインデックスが不要な場合、不要なクエリの使用を回避するためのヒント、インデックスとクエリの機能をできる限り最適化するためのヒントについて概説します。

また、クエリとインデックスの作成に関する Oak ドキュメントも参照してください。AEM 6 における新しい概念であるインデックスに加えて、Oak クエリの構文も大きく異なります。以前の AEM インストールからコードを移行する際にはこの違いを考慮する必要があります。

クエリを使用する場面 when-to-use-queries

リポジトリと分類の設計 repository-and-taxonomy-design

リポジトリの分類を設計する際は、いくつかの要因を考慮する必要があります。特に重要なのは、アクセス制御、ローカラリゼーション、コンポーネント、ページプロパティの継承です。

こうした事柄に対応する分類を設計する一方で、インデックス設計の「トラバーサビリティ」についても検討することも重要です。トラバーサビリティとは、この文脈では、パスに基づいて予想どおりにコンテンツにアクセスできるようにする分類の機能を言います。トラバーサビリティは、多数のクエリを実行しなければならないシステムに比べて保守が簡単な、よりパフォーマンスの高いシステムの実現に役立ちます。

また、分類を設計する際は、順序が重要かどうかを検討することが重要です。明確な順序が不要な場合および多数の兄弟ノードが予想される場合は、sling:Folderoak:Unstructured などの順序がないノードタイプを使用することを推奨します。順序付けが必要な場合は、nt:unstructured および sling:OrderedFolder の方が適切です。

コンポーネント内のクエリ queries-in-components

クエリは、AEM システムでの実行時に大きい負荷がかかり得る処理の 1 つなので、コンポーネント内ではできる限りクエリを回避するようにします。ページがレンダリングされるたびに複数のクエリを実行すると、システムのパフォーマンス低下につながります。コンポーネントのレンダリング時にクエリが実行されることを回避するには、ノードの走査 ​と​ 結果の先取り ​という 2 つの方法があります。

ノードの走査 traversing-nodes

必要なデータの場所を事前に把握できるようにリポジトリーを設計している場合は、クエリを実行してデータを検索せずに、必要なパスからこのデータを取得するコードをデプロイできます。

例えば、特定のカテゴリに適合するコンテンツのレンダリングが行われます。1 つの方法として、コンテンツをカテゴリプロパティで整理し、クエリを実行して、カテゴリ内の項目を表示するコンポーネントに入力できるようにします。

より優れた方法は、このコンテンツを手動で取得できるように、カテゴリ別の分類に構造化することです。

例えば、コンテンツが次のような分類に格納されている場合です。

/content/myUnstructuredContent/parentCategory/childCategory/contentPiece

/content/myUnstructuredContent/parentCategory/childCategory ノードは簡単に取得でき、その子ノードを解析してコンポーネントのレンダリングに使用できます。

さらに、小規模または一様な結果セットを扱う場合は、同じ結果セットを返すためにクエリを作成するよりも、リポジトリーを走査して必要なノードを収集するほうが速い場合があります。一般的な考慮事項として、クエリはできる限り使用せずに済ませる必要があります。

結果の先取り prefetching-results

コンテンツやコンポーネントの要件によっては、必要なデータを取得する方法としてノードの走査を使用できない場合があります。その場合は、エンドユーザーに最適なパフォーマンスを保証するために、コンポーネントがレンダリングされる前に必要なクエリを実行する必要があります。

コンポーネントで必要とされる結果をオーサリング時にまとめて計算でき、さらにコンテンツがその後も変更されないとわかっている場合は、オーサーがダイアログで設定を適用するときにクエリを実行できます。

データまたはコンポーネントが定期的に変更される場合は、スケジュールに従って、または基礎データの更新リスナーを使用してクエリを実行できます。その後、結果をリポジトリ内の共有場所に書き込むことができます。このデータを必要とするコンポーネントは、実行時にクエリを実行しなくても、この 1 つのノードから値を取り出すことが可能です。

クエリの最適化 query-optimization

インデックスを使用していないクエリを実行すると、ノードの走査に関する警告がログに記録されます。このクエリが頻繁に実行されるものである場合は、インデックスを作成する必要があります。特定のクエリが使用しているインデックスを確認するには、クエリの説明を実行ツールを推奨します。さらに情報を得るために、関連する検索 API の DEBUG ログを有効にすることもできます。

NOTE
インデックスの定義を変更したら、インデックスを再構築(再インデックス)する必要があります。インデックスのサイズによっては、この処理を終えるまでにある程度時間がかかることがあります。

複雑なクエリを実行するときは、クエリを複数の小さなクエリに分割し、後からコードによってデータを結合するほうが、パフォーマンスが向上することがあります。その場合のレコメンデーションは、2 つの方法のパフォーマンスを比較し、当該のユースケースでどちらの選択肢が優れているか確認することです。

AEM では、次の 3 つの方法でクエリを記述できます。

  • QueryBuilder API を使用(推奨)
  • XPath を使用(推奨)
  • SQL2 を使用

すべてのクエリは実行前に SQL2 に変換されますが、クエリ変換のオーバーヘッドはごくわずかなので、クエリ言語を選択するときの主な懸念事項は可読性と開発チームの安心感ということになります。

NOTE
QueryBuilder を使用する場合、QueryBuilder はデフォルトで結果数を算出します。Jackrabbit の以前のバージョンと比べて、Oak ではこの処理に時間がかかります。これを補うために、guessTotal パラメーターを使用できます。

クエリの説明を実行ツール the-explain-query-tool

他のクエリー言語と同様に、クエリー最適化の最初の手順は、クエリーの実行方法を把握することです。これをおこなうには、操作ダッシュボードにあるクエリの説明を実行ツールを使用します。このツールを使用すると、クエリにプラグインして説明を取得できます。クエリによって、大規模なリポジトリ、実行時間および使用されるインデックスに関する問題が引き起こされる場合は、警告が表示されます。このツールでは、低速なクエリやよく使用されるクエリのリストを読み込み、これらを説明および最適化できます。

クエリのための DEBUG ログ debug-logging-for-queries

Oak による使用するインデックスの選択方法と、クエリエンジンによるクエリの実際の実行方法に関する追加情報を得るために、DEBUG ログ設定を以下のパッケージに追加できます。

  • org.apache.jackrabbit.oak.plugins.index
  • org.apache.jackrabbit.oak.query
  • com.day.cq.search

クエリーのデバッグが完了したら、必ずこのロガーを削除してください。ロガーは大量のアクティビティを出力する傾向があり、最終的にはログファイルでディスクがいっぱいになる場合があります。

この方法について詳しくは、ログに関するドキュメントを参照してください。

インデックスの統計 index-statistics

Lucene では、インデックス付きのコンテンツに関する詳細(各インデックス内に存在するドキュメントのサイズと数を含む)を提供する JMX Bean が登録されます。

これを確認するには、JMX コンソール(https://server:port/system/console/jmx)にアクセスしてください。

JMX コンソールにログインしたら、検索を実行して Lucene Index Statistics を探します。他のインデックス統計は、IndexStats MBean にあります。

クエリー統計については、Oak Query Statistics という名前の MBean を参照してください。

Luke などのツールを使用してインデックスを詳しく調べる場合は、Oak コンソールを使用して NodeStore のインデックスをファイルシステムディレクトリにダンプする必要があります。これを実行する手順について詳しくは、Lucene のドキュメントを参照してください。

また、JSON 形式でシステム内のインデックスを抽出できます。このためには、https://server:port/oak:index.tidy.-1.json にアクセスする必要があります。

クエリ制限 query-limits

開発中

低いしきい値を oak.queryLimitInMemory(例:10000)と Oak.queryLimitReads(例:5000)に設定し、queryLimitReads UnsupportedOperationException が発生して「The query read more than x nodes…」と表示された場合に高負荷のクエリを最適化します。

これにより、リソースを大量に消費するクエリ(インデックスを使用していないクエリや、あまり網羅的でないインデックスを使用しているクエリ)を避けることができます。例えば、100 万個のノードを読み取るクエリでは I/O が増加し、アプリケーションの全体的なパフォーマンスに悪影響が生じます。上述のような制限が原因で失敗するクエリは、分析して最適化する必要があります。

デプロイメント後 post-deployment

  • ログを監視して、大規模なノードの走査やヒープメモリの大量使用を引き起こしているクエリがないかどうかを調べます。

    • *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を参照してください。

効率的なインデックス作成のヒント tips-for-creating-efficient-indexes

インデックスを作成する必要がありますか? should-i-create-an-index

インデックスを作成または最適化する際にまず考える必要があるのは、その状況でインデックスが必要かどうかという点です。そのクエリを一度またはごくまれにしか実行せず、システムのオフピーク時にバッチ処理で実行する場合は、インデックスを作成しないほうが良い場合があります。

インデックスを作成すると、そのインデックスが付けられたデータを更新するたびに、インデックスも更新する必要が生じます。この処理はシステムのパフォーマンスに影響するので、インデックスは必要な場合にのみ作成する必要があります。

また、インデックスは、インデックス内に含まれるデータが十分に一意である場合にのみ役立ちます。ある本のインデックス(索引)と、その本で取り上げられているトピックについて考えてみましょう。テキスト内の一連のトピックに関するインデックスを作成する場合、通常、エントリは数百から数千個になります。作成したインデックスを使用すると、ページのサブセットにすばやくジャンプして、探している情報をすばやく見つけることができます。インデックスに 2、3 個のエントリしかなく、それぞれが数百ページを指している場合、インデックスはまったく役に立ちません。これと同じ概念が、データベースインデックスにも当てはまります。一意の値がいくつかしか存在しない場合、インデックスは役立ちません。また、サイズが大きくなりすぎてインデックスが役に立たなくなる場合もあります。インデックス統計を見るには、上記のインデックス統計を参照してください。

Lucene インデックスとプロパティインデックスのどちらを使用するか lucene-or-property-indexes

Lucene インデックスは Oak 1.0.9 で導入され、AEM 6 の初回起動時に導入されたプロパティインデックスに対して、強力な最適化を提供します。Lucene インデックスまたはプロパティインデックスのどちらを使用するかを決定する際は、次の点を考慮してください。

  • Lucene インデックスは、プロパティインデックスよりも多くの機能を提供します。例えば、プロパティインデックスでは 1 つのプロパティにしかインデックスを作成できませんが、Lucene インデックスでは多数のプロパティを含めることができます。Lucene インデックスで使用可能なすべての機能について詳しくは、ドキュメントを参照してください。
  • Lucene インデックスは非同期です。パフォーマンスが大幅に向上する一方で、リポジトリにデータが書き込まれるタイミングとインデックスが更新されるタイミングとの間に遅延が生じる場合もあります。クエリが 100%の正確な結果を返すことが重要な場合は、プロパティインデックスが必要です。
  • Lucene インデックスは、非同期式という特性上、一意性制約を適用できません。この制約が必要な場合は、プロパティインデックスを使用する必要があります。

一般に、プロパティインデックスを使用する必要性がない限り、より高いパフォーマンスと柔軟性のメリットを得るために Lucene インデックスを使用することをお勧めします。

Solr インデックス作成 solr-indexing

AEM では、Solr のインデックス作成もデフォルトでサポートされています。これはフルテキスト検索をサポートするために使用されますが、あらゆるタイプの JCR クエリをサポートするためにも使用できます。AEM インスタンスに、検索に負荷がかかるデプロイメント(同時ユーザー数が多い検索主導型 web サイトなど)で必要なクエリ数を処理するための CPU 処理能力がない場合は、Solr を検討する必要があります。また、Solr をクローラーベースの手法で実装して、プラットフォームのより高度な機能の一部を活用することもできます。

Solr インデックスは、AEM サーバー上で開発環境用に埋め込んで実行するように設定することも、リモートインスタンスにオフロードして、実稼動環境とステージング環境での検索のスケーラビリティを向上させることもできます。検索のオフロードによりスケーラビリティが向上しますが、遅延が生じるので、必要な場合を除きお勧めしません。Solr 統合の設定方法と Solr インデックスの作成方法について詳しくは、Oak クエリとインデックス作成に関するドキュメントを参照してください。

NOTE
統合型の Solr 検索アプローチを採用すると、インデックス作成を Solr サーバーにオフロードできます。クローラーベースの手法で Solr サーバーのより高度な機能を使用する場合は、追加の設定作業が必要になります。

ただし、このアプローチには欠点が 1 つあります。AEM のクエリはデフォルトで ACL を適用するので、ユーザーがアクセス権を持たない結果は表示されませんが、検索を Solr サーバーにオフロードするとこの非表示機能が働かなくなります。この方法で検索をオフロードする場合は、ユーザーに見せてはいけない結果を表示していないかを特に注意して確認する必要があります。

このアプローチが適しているユースケースとしては、検索データを複数のソースから集めなければならない場合が考えられます。例えば、AEM でホストされているサイトと、サードパーティのプラットフォームでホストされている 2 つ目のサイトがある場合などです。この場合は、両方のサイトのコンテンツをクロールし、その結果を統合インデックスに格納するよう Solr を設定できます。こうすることで、クロスサイト検索が可能になります。

設計上の考慮事項 design-considerations

Lucene インデックスに関する Oak のドキュメントでは、以下のとおり、インデックス設計時の考慮事項をいくつか挙げています。

  • クエリで異なるパス制限を使用する場合は、evaluatePathRestrictions を使用します。こうすることで、指定したパスの下にある結果のサブセットをクエリで返し、そのクエリに基づいて結果をフィルタリングできます。それ以外の場合は、クエリはリポジトリ内のクエリパラメーターに一致するすべての結果を検索してから、パスに基づいて結果をフィルタリングします。

  • クエリで並べ替えを使用する場合は、並べ替えるプロパティの明示的なプロパティ定義を用意し、そのプロパティの orderedtrue に設定します。こうすることで、結果がインデックスどおりの順番に並ぶので、コストがかかる並べ替え処理をクエリ実行時に行う必要がなくなります。

  • インデックスには必要なものだけを追加します。不要な機能やプロパティを追加すると、インデックスの増大とパフォーマンスの低下につながります。

  • プロパティインデックスでは、一意のプロパティ名を使用すると、インデックスのサイズを削減できます。しかし Lucene インデックスでは、統一されたインデックスを実現するために、nodeTypesmixins を使用する必要があります。特定の nodeType または mixin をクエリすると、nt:base をクエリするよりもパフォーマンスが向上します。この方法を使用する場合は、当該の nodeTypesindexRules を定義します。

  • クエリを特定のパスでのみ実行する場合は、そのパスの下でインデックスを作成します。インデックスにリポジトリのルートを含める必要はありません。

  • インデックスを付けるすべてのプロパティが関連しているときは、Lucene ができるだけ多くのプロパティ制限をネイティブで評価できるようにするために、単一のインデックスを使用します。また、結合を実行する場合でも、クエリは 1 つのインデックスだけを使用します。

CopyOnRead copyonread

NodeStore がリモートに格納されている場合は、CopyOnRead というオプションを有効にできます。このオプションを使用すると、リモートインデックスが読み込まれるときに、リモートインデックスがローカルのファイルシステムに書き込まれます。このオプションは、こうしたリモートインデックスに対して頻繁に実行されるクエリのパフォーマンス向上に役立ちます。

これは OSGi コンソールの LuceneIndexProvider サービスで設定でき、Oak 1.0.13 の時点ではデフォルトで有効です。

インデックスの削除 removing-indexes

インデックスを削除するときは、必ず type プロパティを disabled に設定して一時的にインデックスを無効にしたうえで、実際に削除する前にテストを実施し、アプリケーションが正しく動作するか確認することを推奨します。インデックスは無効にしている間は更新されないので、再度有効にした場合に正しいコンテンツを含んでいない可能性があり、インデックスの再作成が必要になることがあります。

TarMK インスタンスのプロパティインデックスを削除した後は、使用されていたディスクスペースを再利用するために、圧縮を実行する必要があります。Lucene インデックスの場合、実際のインデックスコンテンツは BlobStore に格納されているので、データストアのガベージコレクションが必要になります。

MongoDB インスタンスのインデックスを削除する場合、削除のコストはインデックスのノードの数に比例します。大量のインデックスを削除すると問題が生じることがあるので、インデックスを無効にしてから、メンテナンスウィンドウ中に oak-mongo.js などのツールを使用して削除する方法が推奨されます。この方法は、データの不一致を引き起こす可能性があるため、通常のノードコンテンツには使用できません。

NOTE
oak-mongo.js について詳しくは、Oak のドキュメントの Command Line Tools のセクションを参照してください。

JCR クエリチートシート jcrquerycheatsheet

効率的な JCR クエリとインデックス定義を作成できるようにするため、開発時に JCR クエリチートシートをダウンロードして参照用として使用できます。これには QueryBuilder、XPath、SQL-2 のクエリの例が収録されていて、クエリのパフォーマンスの点で異なる動作をする複数のシナリオに対応できます。また、Oak インデックスの作成またはカスタマイズ方法に関するレコメンデーションも収録されています。このチートシートの内容は、AEM 6.5 および AEM as a Cloud Service に適用されます。

インデックス再作成 re-indexing

ここでは、Oak インデックスの再インデックスを実行する理由として許容できるもの​ のみ ​を概説します。

次に説明する理由以外で Oak インデックスの再インデックスを開始しても、動作が変わったり問題が解決したりすることは​ なく、AEM に不必要に高い負荷がかかります。

以下の各表に記載されている理由に該当する場合を除き、Oak インデックスの再インデックスは避けるようにしてください。

NOTE
以下の各表を参照して再インデックスが有効であるかどうかを判断する前に、必ず ​次のことを確認してください。
  • クエリが正しいこと
  • クエリが予期したインデックスに解決されること(クエリの説明を実行を使用)
  • インデックス作成プロセスが完了していること

Oak インデックスの設定の変更 oak-index-configuration-changes

エラーがないときに Oak インデックスの再インデックスが許容される唯一の状況は、Oak インデックスの設定が変更された場合です。

再インデックスに着手する前には必ず、AEM の全体的なパフォーマンスに対する影響を適切に検討し、アクティビティが少ない期間やメンテナンスウィンドウ中に再インデックスを実行する必要があります。

以下の節では、発生する可能性がある問題と解決策について詳しく説明します。

プロパティインデックスの定義の変更 property-index-definition-change

  • 適用対象:

  • 症状:

    • プロパティインデックスの定義を更新する前に存在していたノードが結果に見つからない
  • 検証方法:

    • 更新したインデックス定義をデプロイする前に、見つからないノードが作成または変更されていたかどうかを確認します。
    • 見つからないノードのjcr:createdまたはjcr:lastModifiedプロパティをインデックスの変更時間と照合して検証します。
  • 解決方法:

    • Lucene インデックスをインデックス再作成します。

    • または、見つからないノードについて処理(安全な書き込み操作)を行います。

      • 手動処理またはカスタムコードが必要です。
      • 見つからない一連のノードを把握する必要があります。
      • ノードでプロパティを変更する必要があります。

Lucene インデックスの定義の変更 lucene-index-definition-change

  • 適用対象:

  • 症状:

    • 予期した結果が Lucene インデックスに含まれない
    • インデックス定義の予期される動作がクエリ結果に反映されない
    • インデックス定義に基づいて予期される出力がクエリプランで報告されない
  • 検証方法:

    • Lucene インデックス統計 JMX Mbean(LuceneIndex)の diffStoredIndexDefinition メソッドを使用して、インデックス定義が変更されているかどうかを検証します。
  • 解決方法:

    • 1.6 より前の Oak バージョン:

    • 1.6 以降の Oak バージョン

      • 既存の内容が変更の影響を受けない場合は、更新のみが必要です。

        • [oak:queryIndexDefinition]@refresh=true を設定して、Lucene インデックスを更新します。
      • それ以外の場合は、Lucene インデックスをインデックス再作成します。

        • メモ:新しいインデックスが再作成されるまで、前回の正常なインデックス再作成(または最初のインデックス作成)のインデックス状態が使用されます。

エラーと例外の状況 erring-and-exceptional-situations

次の表では、Oak インデックスのインデックス再作成によって問題が解決される、唯一のエラーや例外の状況について説明しています。

以下に記載する条件と一致しない問題が AEM で発生する場合は、いずれのインデックスについても再インデックスを実行​ しない ​でください。再インデックスを実行しても、問題は解決しません。

以下の節では、発生する可能性がある問題と解決策について詳しく説明します。

Lucene インデックスのバイナリが見つからない lucene-index-binary-is-missing

  • 適用対象:

  • 症状:

    • 予期した結果が Lucene インデックスに含まれない
  • 検証方法:

    • Lucene インデックスのバイナリが見つからないという例外がエラーログファイルに記録されます。
  • 解決方法:

    • リポジトリ走査チェックを実行します。例:

      http://localhost:4502/system/console/repositorycheck

      リポジトリの走査により(lucene ファイル以外の)他のバイナリが欠落していないか判断

    • Lucene インデックス以外のバイナリが見つからない場合は、バックアップから復元します。

    • それ以外の場合は、すべての Lucene インデックスの再インデックスを実行します。

    • メモ:

      この状況はデータストアの設定が誤っていることを示しており、バイナリ(アセットのバイナリなど)が見つからなくなる原因となる可能性があります。

      この場合は、正常であることがわかっている最新のリポジトリバージョンに復元し、見つからないすべてのバイナリを回復します。

Lucene インデックスのバイナリが破損している lucene-index-binary-is-corrupt

  • 適用対象:

  • 症状:

    • 予期した結果が Lucene インデックスに含まれない
  • 検証方法:

    • AsyncIndexUpdate(5 秒ごと)が失敗し、次の例外がエラーログに記録されます。

      ...a Lucene index file is corrupt...

  • 解決方法:

    • Lucene インデックスのローカルコピーを削除します。

      1. AEM を停止します。
      2. crx-quickstart/repository/indexにある Lucene インデックスのローカルコピーを削除
      3. AEM を再起動します。
    • この手順を実行しても問題が解決せず、AsyncIndexUpdate 例外が引き続き発生する場合は、次の手順に従います。

      1. エラーがあるインデックスをインデックス再作成します。
      2. さらに、アドビサポートチケットを提出します。

インデックス再作成の方法 how-to-re-index

NOTE
AEM 6.5 では、MongoMK または RDBMK リポジトリでのインデックス再作成に使用できる方法は oak-run.jar のみです。

プロパティインデックスのインデックス再作成 re-indexing-property-indexes

Lucene プロパティインデックスのインデックス再作成 re-indexing-lucene-property-indexes

NOTE
以上の節は、Apache Oak のドキュメントの内容を要約し、AEM のコンテキストにおける Oak のインデックス再作成に関するガイダンスをまとめたものです。

バイナリのテキスト事前抽出 text-pre-extraction-of-binaries

テキストの事前抽出とは、分離されたプロセスを介してデータストアから直接バイナリからテキストを抽出および処理し、抽出したテキストを以降の Oak インデックスの再/インデックス化に直接公開するプロセスです。

  • Oak のテキスト事前抽出は、/oak:index/damAssetLucene など、デプロイされた Oak インデックスによるフルテキスト検索に適した抽出可能なテキストを含む大量のファイル(バイナリ)があるリポジトリで、Lucene インデックスのインデックス再作成/インデックス作成を実行する場合に推奨されます。このようなファイルの例としては、PDF、Word Doc、PPT、TXT などがあります。
  • テキスト事前抽出は、Lucene インデックスのインデックス再作成/インデックス作成の場合にのみ利点があります。Oak プロパティインデックスの場合、プロパティインデックスはバイナリからテキストを抽出しないので、利点がありません。
  • テキスト事前抽出は、大量のテキストを含むバイナリ(PDF、Doc、TXT など)のフルテキストインデックス再作成には大きな効果がありますが、画像には抽出可能なテキストが含まれないので、画像のリポジトリでは同様の効果は得られません。
  • テキスト事前抽出では、フルテキスト検索に関連するテキストの抽出がきわめて効率的に実行され、きわめて効率的に使用できるような方法で Oak の再インデックス/インデックス作成プロセスに渡されます。

テキスト事前抽出を使用できる状況 when-can-text-pre-extraction-be-used

バイナリ抽出が有効な​ 既存 ​の Lucene インデックスのインデックス再作成

  • インデックス再作成では、リポジトリ内の​ すべての ​候補コンテンツが処理されます。フルテキストを抽出するバイナリが多数ある場合や複雑である場合、フルテキスト抽出を実行するための計算負担が AEM にかかります。テキスト事前抽出では、テキスト抽出の「計算コストが高い作業」が分離されたプロセスに移行され、このプロセスが直接 AEM のデータストアにアクセスするので、AEM におけるオーバーヘッドやリソースの競合が回避されます。

バイナリ抽出が有効になった​ 新しい Lucene インデックスの AEM へのデプロイメントのサポート

  • 新しいインデックス(バイナリ抽出が有効になった)が AEM にデプロイされると、非同期フルテキストインデックス作成の次回実行時に、すべての候補コンテンツのインデックスが自動的に作成されます。前述のインデックス再作成の説明と同じ理由で、これにより AEM に過度の負荷がかかる可能性があります。

テキスト事前抽出を使用できない状況 when-can-text-pre-extraction-not-be-used

テキスト事前抽出は、リポジトリに追加された新しいコンテンツには使用できません。また、使用する必要もありません。

リポジトリに追加された新しいコンテンツには、非同期フルテキストインデックス作成プロセスによって、インデックスが必然的かつ増分的に作成されます(デフォルトでは 5 秒ごと)。

Web UI を介したアセットのアップロードやプログラムによるアセットの取り込みなど、AEM の通常の操作では、新しいバイナリコンテンツのフルテキストインデックスが自動的かつ増分的に作成されます。データの量は増分であり、比較的少ないので(およそ 5 秒でリポジトリに永続化できるデータの量)、AEM では、全体的なシステムパフォーマンスに影響を及ぼすことなく、インデックス作成時にバイナリからのフルテキスト抽出を実行できます。

テキスト事前抽出を使用するための前提条件 prerequisites-to-using-text-pre-extraction

  • フルテキストバイナリ抽出を実行する Lucene インデックスのインデックス再作成、または既存のコンテンツのバイナリのフルテキストインデックスを作成する新しいインデックスのデプロイ

  • テキストを事前抽出するコンテンツ(バイナリ)がリポジトリ内に存在すること

  • CSV ファイルの生成および最終的なインデックス再作成の実行のためのメンテナンスウィンドウ

  • Oak バージョン 1.0.18 以降、1.2.3 以降

  • oak-run.jar バージョン 1.7.4 以降

  • AEM のインデックス作成インスタンスからアクセス可能な、抽出されたテキストを格納するファイルシステムフォルダー/共有

    • テキスト事前抽出の OSGi 設定には、AEM インスタンスから直接それらのファイルにアクセスできるように、抽出されたテキストファイルへのファイルシステムパスが必要です(ローカルドライブまたはファイル共有マウント)。

テキスト事前抽出を実行する方法 how-to-perform-text-pre-extraction

NOTE
以下で概説する 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 コマンドでパスを指定された通りに)、CSV ファイルが​ 新規 ​作成されます。CSV ファイルは、テキスト事前抽出プロセス(手順 1~2)の個々の実行の際に再利用され​ ません

ファイルシステムへのテキストの事前抽出

手順 2(a ~ c)は、AEM の通常の操作中に実行できます。この手順では、データストアのみとやり取りがおこなわれます。

2a. oak-run.jar --tika を実行して、(1b)で生成した CSV ファイルに列挙されているバイナリノードのテキストを事前抽出します。

2b. (2a)で開始されたプロセスが、CSV で定義されているバイナリノードにデータストアで直接アクセスし、テキストを抽出します。

2c.抽出されたテキストが、Oak のインデックス再作成プロセス(3a)で取り込み可能な形式でファイルシステムに格納されます。

事前抽出されたテキストは、CSV 内でバイナリのフィンガープリントによって識別されます。バイナリファイルが同じである場合、事前抽出された同じテキストを AEM インスタンス間で使用できます。通常、AEM パブリッシュは AEM オーサーのサブセットなので、AEM オーサーから事前抽出されたテキストは、多くの場合、AEM パブリッシュのインデックス再作成にも使用できます(抽出されたテキストファイルに対するファイルシステムアクセス権を AEM パブリッシュが持っていることを前提とします)。

事前抽出されたテキストは、時間の経過とともに徐々に追加できます。テキスト事前抽出では、以前に抽出済みのバイナリの抽出がスキップされるので、将来、インデックス再作成を再び実行する必要が生じた場合に備えて、事前抽出されたテキストを保管しておくことをお勧めします(抽出された内容が過度に大きくないことを前提とします)。過度に大きい場合は、テキストはよく圧縮されるので、暫定的にコンテンツを圧縮することを検討してください)。

抽出されたテキストファイルからフルテキストを取得して Oak インデックスの再インデックスを実行

この操作ではノードストアが走査され、システムに大きな負荷がかかる可能性があるので、手順 1(3a~b)はメンテナンスウィンドウ中やあまり使用されていない時間に実行してください。

3a. Lucene インデックスの再インデックスが AEM で実行されます。

3b. Apache Jackrabbit Oak DataStore PreExtractedTextProvider の OSGi 設定(抽出されたテキストをファイルシステムパスで指定します)では、Oak は、抽出されたファイルからフルテキストを取得するよう指示されており、リポジトリに格納されているデータに Oak が直接アクセスして処理することを回避します。

recommendation-more-help
19ffd973-7af2-44d0-84b5-d547b0dffee2