2.10. キャッシュのインデックス作成とクエリー
Data Grid キャッシュをクエリーすると、データを分析してフィルタリングし、リアルタイムで知見を得ることができます。たとえば、プレイヤー同士が競争して点数を獲得するオンラインゲームを思い浮かべてください。上位 10 位のプレイヤーを表示するリーダーボードを実装する場合は、以下のように、ある時点で最高得点を獲得したプレイヤーを特定して、最大 10 位までの結果に制限するといったクエリーを作成できます。
QueryFactory queryFactory = Search.getQueryFactory(playersScores); Query topTenQuery = queryFactory .create("from com.redhat.PlayerScore ORDER BY p.score DESC, p.timestamp ASC") .maxResults(10); List<PlayerScore> topTen = topTenQuery.execute().list();
前述の例では、何百万もあるキャッシュエントリーから基準とあったエントリーを 10 件特定できるので、クエリーを使用する利点がわかります。
ただし、パフォーマンスへの影響の面では、インデックス操作とクエリー操作に関するトレードオフを考慮する必要があります。キャッシュをインデックス化するように Data Grid を設定すると、クエリーがはるかに速くなります。インデックスなしでは、クエリーがキャッシュ内のすべてのデータをチェックする必要があるので、データの種類と量に応じて、結果が遅くなります。
インデックス化が有効な場合に書き込みのパフォーマンスがある程度、低下します。インデックスする内容を理解し、慎重にプランニングすることで、最も深刻な影響は回避できます。
最も効果的な方法として、必要なフィールドだけをインデックス化するように Data Grid を設定できます。Plain Old Java Objects(POJO) を保存するか、Protobuf スキーマを使用するかに関係なく、アノテーションをつけるフィールドが多いと、Data Grid がインデックス構築にかかる時間が長くなります。フィールドが 5 つある POJO があるものの、この内 2 つのフィールドだけをクエリーする必要がある場合は、必要のない 3 つのフィールドをインデックス化しないように Data Grid を設定してください。
Data Grid には、インデックス操作を調整するオプションが複数あります。たとえば、Data Grid はデータとは違う形式でインデックスを保存し、メモリーではなく、ディスクにインデックスを保存します。Data Grid は、エントリーが追加、変更、削除されるたびに、インデックスライターを使用してキャッシュとインデックスを同期させます。インデックスを有効にした後、書き込みが遅くなり、インデックスが原因でパフォーマンスが低下したと考えられる場合は、ディスクに書き込む前に、インデックスをメモリーバッファーに長く保持することができます。その結果、インデックス処理が高速化され、書き込みスループットの低下を抑えることができますが、メモリーが多く消費されます。ただし、ほとんどのデプロイメントでは、デフォルトのインデックス設定が適しており、書き込みがあまり遅くならないようになっています。
たとえば、書き込みの多いキャッシュでは、頻繁にクエリーを実行する必要がなく、ミリ秒単位の結果が必要ない場合など、キャッシュにインデックスを作成しないほうが適しているシナリオもあります。すべて実現する内容により、異なります。クエリーが速くなると、読み込みも速くなりますが、インデックス化すると代わりに書き込みが遅くなります。
maxResults
と hit-count-accuracy
の値を適切に設定することで、インデックス付きクエリーのパフォーマンスを向上させることができます。
関連情報
2.10.1. 継続クエリーと Data Grid のパフォーマンス
継続的なクエリーは、アプリケーションに更新の定数ストリームを提供しており、大量のイベントを生成できます。Data Grid は、生成する各イベントにメモリーを一時的に割り当てます。これにより、メモリー不足が発生し、特にリモートキャッシュに対して OutOfMemoryError
例外が発生する可能性があります。このため、パフォーマンスへの影響を回避するために、継続的なクエリーを慎重に設計する必要があります。
Data Grid は、継続的なクエリーのスコープを必要な情報の最小量に制限することを強く推奨します。これを実行するには、プロジェクション および述語を使用できます。たとえば、以下のステートメントでは、エントリー全体ではなく基準に一致するフィールドのサブセットのみに関する結果を表示します。
SELECT field1, field2 FROM Entity WHERE x AND y
また、各 ContinuousQueryListener
は、ブロッキングスレッドを使用せずに受信したすべてのイベントを迅速に処理できるようにすることが重要です。これを実行するには、イベントを不必要に生成するキャッシュ操作を回避する必要があります。