Elasticsearch は、非常に高速なデータ ストレージとクエリ速度を備えたオープンソースの分散型検索エンジンです。ただし、大規模なデータセットと高い同時アクセスに直面すると、Elasticsearch のパフォーマンスも影響を受ける可能性があります。Elasticsearch のパフォーマンスを最大化するには、インデックスを最適化する必要があります。このブログでは、断片化とレプリカの調整、マッピングとアナライザーの使用など、Elasticsearch インデックスの最適化のいくつかの重要な側面を紹介します。
1. シャードとレプリカ
Elasticsearch はシャードとレプリカを使用して、分散ストレージと高可用性を実現します。シャーディングとは、インデックスを複数の部分に分割することです。各部分は独立した Lucene インデックスです。コピーはシャードのバックアップであり、各シャードは複数のコピーを持つことができます。
デフォルトでは、Elasticsearch はインデックスごとに 5 つのプライマリ シャードと 1 つのレプリカを作成し、合計 10 のシャード (5 つのプライマリ シャード + 5 つのレプリカ シャード) を作成します。これは、各インデックスのデータが 10 の部分に分割され、各部分にプライマリ シャードとレプリカ シャードがあることを意味します。小規模なインデックスにはこの設定で十分ですが、大規模なデータ セットに直面する場合は調整が必要になる場合があります。
1.1 プライマリシャードの数を調整する
プライマリ シャードの数の設定は、インデックスの分散パフォーマンスとスケーラビリティに直接影響します。プライマリ シャードの数が少なすぎると、各シャードのデータ量が多すぎて、クラスター内のすべてのノードのコンピューティング リソースを利用できなくなります。プライマリシャードの数が多すぎると、インデックスが分散しすぎて、データの移行や調整に負担がかかります。
一般に、次の 2 つの方法でプライマリ シャードの数を調整できます。
- 新しいインデックスを作成するときにプライマリ シャードの数を指定します。
- 既存のインデックスを再インデックス (再インデックス) し、新しいプライマリ シャードの数を指定します。
実際の運用では、データ量、クエリ頻度、クラスターサイズなどの要因に応じてプライマリシャードの数を調整する必要があります。たとえば、ノードあたり 8 個の CPU コアを持つクラスターの場合、通常、プライマリ シャードの数を 2 のべき乗 (2、4、8、16 など) に設定することをお勧めします。
1.2 部数を調整する
レプリカ数の設定は、インデックスの可用性と読み取りおよび書き込みのパフォーマンスに影響します。レプリカの数が少なすぎると、ノードに障害が発生したときにデータの可用性が保証されません。コピーが多すぎると、ディスク容量とネットワーク帯域幅が過剰に占有され、書き込みパフォーマンスが低下します。
一般に、次の 2 つの方法でレプリカの数を調整できます。
- インデックスを作成するときにレプリカの数を指定します。
- 既存のインデックスに対して API 操作を実行して、レプリカの数を変更します。
プライマリ シャードの数とは異なり、レプリカの数は実際のニーズに応じて動的に調整できます。たとえば、書き込み頻度が高いインデックスの場合、レプリカの数を減らして書き込みパフォーマンスを向上させることができます。クエリ頻度が高いインデックスの場合、レプリカの数を増やしてクエリのパフォーマンスを向上させることができます。
2. マッピング
Elasticsearch では、マッピングはドキュメント フィールドをインデックス内のデータ構造にマッピングするプロセスです。マッピングでは、インデックス内の各フィールドのタイプ、トークナイザー、保存方法などの情報を定義します。これは、検索および集計操作にとって非常に重要です。マッピングを最適化することで、クエリと集計のパフォーマンスを向上させ、インデックスのストレージ領域を削減できます。
2.1 クリアフィールドタイプ
マッピングを定義するときは、各フィールドのタイプをできるだけ明確にする必要があります。Elasticsearch でサポートされるフィールド タイプは次のとおりです。
- 文字列(テキスト, キーワード);
- 数值(long、integer、short、byte、double、float、half_float、scaled_float);
- 日付(日付);
- ブール値 (ブール値);
- バイナリ(バイナリ);
- 地理的位置 (geo_point、geo_shape)。
フィールドの種類を選択するときは、フィールドの実際の意味と使用シナリオに応じて選択する必要があります。たとえば、全文検索が必要なテキスト フィールドの場合、通常はテキスト タイプが使用されます。完全一致が必要なテキスト フィールドの場合は、通常、キーワード タイプが使用されます。さらに、数値フィールドの場合は、フィールドの種類が異なれば集計時のパフォーマンスも異なるため、フィールドを集計する必要があるかどうかにも注意する必要があります。
2.2 デフォルトのマッピングの使用を避ける
Elasticsearch は、ドキュメント内のすべての未定義フィールドをテキスト タイプに自動的にマッピングするデフォルトのマッピングを提供します。ただし、デフォルトのマッピングを使用すると、インデックス用のストレージ領域が無駄になり、クエリのパフォーマンスが低下します。したがって、マッピングを定義するときは、各フィールドのタイプをできるだけ明確にし、デフォルトのマッピングの使用を避ける必要があります。
2.3 フィールドデータの使用
フィールド データは、Elasticsearch の集計操作用のデータ構造であり、ドキュメント フィールドの値をメモリにロードできるため、集計操作のパフォーマンスが向上します。フィールドデータを使用する場合は、次の点に注意する必要があります。
- フィールド データは不変フィールドにのみ適用されます。
- フィールド データはメモリを消費するため、フィールド データの使用を選択する場合はメモリの使用量に注意する必要があります。
- フィールド データは、カーディナリティの高いフィールドではパフォーマンスが低下します。
2.4 ネストされたフィールドの使用
Elasticsearch は、ネストされたフィールド、つまり、あるドキュメント内に別のドキュメントをネストすることをサポートしています。ネストされたフィールドを使用すると、クエリと集計操作が簡素化され、クエリのパフォーマンスが向上します。ネストされたフィールドを使用する場合は、次の点に注意する必要があります。
- ネストされたフィールドの定義はマッピングで行う必要があります。
- ネストされたフィールドを全文で直接検索することはできません。
- ネストされたフィールドを集計操作に使用する場合は、ネストされた集計 (ネストされた集計) を使用する必要があります。
3. アナライザー
Analyzer はテキストを処理するための Elasticsearch のコンポーネントであり、テキストを一連の用語 (用語) に分割し、これらの用語をインデックスに保存できます。アナライザーは、文字フィルター、トークナイザー、トークン フィルターの 3 つのコンポーネントで構成されます。
3.1 文字フィルター
文字フィルターは、HTML タグの削除、特殊文字の変換など、テキストの前処理に使用されます。Elasticsearch は、HTML ストリップ文字フィルター、マッピング文字フィルターなど、いくつかの組み込み文字フィルターを提供します。
3.2 トークナイザー
トークナイザーは、テキストを一連のトークンに分割するために使用されます。Elasticsearch は、標準トークナイザー、ホワイトスペース トークナイザー、キーワード トークナイザーなど、さまざまな組み込みトークナイザーを提供します。さらに、カスタム プラグインを通じてカスタム トークナイザーを実装することもできます。
3.3 用語フィルター
フィルターという用語は、単語で区切られた用語をフィルター、変更、または置換するために使用されます。Elasticsearch は、小文字トークン フィルター、停止トークン フィルター、同義語トークン フィルターなど、さまざまな組み込みの用語フィルターを提供します。さらに、カスタム プラグインを通じてカスタム用語フィルターを実装することもできます。
3.4 アナライザーの最適化
Analyzer を使用する場合は、次の点に注意する必要があります。
- 処理時間が長くなるので、文字フィルターと用語フィルターの数を最小限に抑えます。
- 実際のニーズに応じて、適切なトークナイザーと用語フィルターを選択します。
- 全文検索を行う場合は、インデックス作成時と同じ Analyzer を使用する必要があります。
エピローグ
Elasticsearch インデックスを最適化することで、検索と集計のパフォーマンスが向上し、占有されるストレージ容量を削減できます。インデックスの最適化には一定のスキルと経験が必要ですが、関連する知識を習得していれば、ビジネスにより効率的な検索および分析サービスを提供できます。