ElasticsearchはDocValuesとFielddataを深く理解しています
Elasticsearch Depth Understanding Doc Values
DocValues
DocValuesとは何ですか
DocValuesは一種の列型データストレージ構造(docid、termvalues)であることを簡単に説明します。
転置インデックスの利点は、特定のアイテムを含むドキュメントを検索すること、つまり、Termを介して対応するdocidを検索することです。
- フィールド反転
フィールド | Doc_1 | Doc_2 | Doc_3 |
---|---|---|---|
褐色 | バツ | バツ | |
犬 | バツ |
- Field2反転
フィールド2 | Doc_1 | Doc_2 | Doc_3 |
---|---|---|---|
ブラウン2 | バツ | バツ | |
dog2 | バツ |
これにより、doc1およびdoc2としてbrownを含むドキュメントをすばやく見つけることができます。
ただし、他の方向とは逆の操作、つまりdocidに従ってドキュメントの指定されたフィールド(Field2)の値を見つけることは効率的ではありません。ただし、このタイプのアクセスモードは、集計、並べ替え、および詳細クエリに必要です。
インデックスをトラバースすることはお勧めできないことを宣言します。これは遅く、拡張が困難です。用語とドキュメントの数が増えると、実行時間も増えます。上記の問題を解決するために、Doc値を使用して2つの関係を転置することでこの問題を解決します。
(doc_value文字列をテキストタイプにすることはできず、キーワードのみにすることができます)
- フィールドdocvalues
Doc | フィールド |
---|---|
Doc_1 | 褐色 |
Doc_2 | 褐色 |
Doc_3 | 犬 |
- Field2のDocvalues
Doc | フィールド2 |
---|---|
Doc_1 | ブラウン2 |
Doc_2 | ブラウン2 |
Doc_3 | dog2 |
例えば:
Field2、count(1)をテーブルから選択します。ここで、Field = 'brown' group by Field2
上記のSQLと同様の集計クエリを完了するには、次のようにします。
- データ範囲を配置します。 Field = ’brown’のdocid(doc1、doc2)を取得し、転置インデックスを使用します
- 集計計算を実行します。 doc1とdoc2によると、Field2にあるフィールドはbrown2であり、計算結果は集計によって取得されます。 browm2のcount(1)= 2。
検索と集計は密接に関連しています。検索では転置インデックスを使用してドキュメントを検索し、集計操作でドキュメント値のデータを収集して集計します。
DocValuesの仕組み
DocValuesの公式ドキュメントの紹介は、高速で効率的でメモリに優しいものです。
-
1. DocValuesは、インデックス作成時に転置インデックスと同時に生成され、不変です。反転行と同じで、luceneファイルに保存されます(ディスクにシリアル化されます)。
Luceneファイル操作は、JVMスタック内の常駐データではなく、オペレーティングシステムのキャッシュに依存して管理します。この機能は、ファイル処理のパフォーマンスを確保するためにesを使用するときにosに十分なメモリを割り当てる必要があることを決定します。詳細な設定については、を参照してください。 本番環境でのelasticsearchの構成に関する推奨事項 -
2.DocValuesは列圧縮を使用します
最新のCPUの処理速度はディスクよりも桁違いに速いため、解凍には追加のCPU操作が必要ですが、ディスクから読み取る必要のあるデータの量を減らすことは常に有益です。
DocValuesは多くの圧縮技術を使用しています。次の圧縮モードを順番に検出します。
- すべての値が異なる(または欠落している)場合は、フラグを設定してこれらの値を記録します
- これらの値が256未満の場合、単純なコーディングテーブルが使用されます
- これらの値が256より大きい場合は、最大公約数があるかどうかを確認してください
- 最大公約数がない場合は、最小値から始めて、エンコードのオフセットを均一に計算します
これらの圧縮モードは、DEFLATEやLZ4などの従来の一般的な圧縮方法ではありません。列型ストレージの構造は厳密かつ明確に定義されているため、特別なモードを使用することで、一般的な圧縮アルゴリズム(LZ4など)よりも高い圧縮効果を実現できます。
、文字タイプは、序数テーブルを使用して同様にエンコードされます。文字タイプは、重複排除後にIDを割り当ててシーケンステーブルに保存され、これらのIDは数値タイプのドキュメント値と同じように使用されます。つまり、文字タイプは数値タイプと同じ圧縮特性を持っています。
シーケンステーブル自体にも、固定長、可変長、プレフィックス文字エンコードなど、多くの圧縮技術があります。
- 3.DocValuesサポートの無効化
この値はデフォルトでアクティブになっています。不要な場合は、doc_values:falseを設定して無効にすることができます。
DocValuesではサポートされていません
上記の紹介によると、 ドキュメント値は分析された文字列フィールドをサポートしていません はい、最初のようにフィールドが分析された場合、docvaluesは分析フェーズで2つのdocvalues(theとfirst)として保存され、次のようになります。
フィールド | カウント |
---|---|
インクルード | 1 |
最初 | 1 |
の代わりに
フィールド | カウント |
---|---|
最初 | 1 |
私たちが望む結果をどのように達成したいですか?フィールドデータ。
フィールドデータ
doc値は分析された文字列を生成しません。ただし、fielddataデータ構造を使用しているため、これらのフィールドは引き続き集計できます。ドキュメント値とは異なり、fielddataはメモリ内で100%構築および管理され、JVMメモリヒープ内に存在します。 fielddataは、すべてのフィールドのデフォルト設定です。
メモリ使用量に注意してください
いくつかの機能:
-
- fielddataは遅延ロードされます。分析文字列を集計したことがない場合、fielddataはメモリに読み込まれず、クエリ時に作成されます。
-
- フィールドデータはフィールドに基づいて読み込まれ、フィールドを積極的に使用するだけでフィールドデータの負担が増大します。
-
- fielddataは、クエリがヒットしたかどうかに関係なく、(その特定のフィールドの)インデックス内のすべてのドキュメントをロードします。ロジックは次のとおりです。クエリがドキュメントX、Y、およびZにアクセスする場合、次のクエリで他のドキュメントにアクセスする可能性があります。
-
- 十分なスペースがない場合は、LRUアルゴリズムを使用してフィールドデータを削除します。
したがって、fielddataはJVMで合理的に使用する必要があります。そうしないと、パフォーマンスに影響します。
使用できるindices.fielddata.cache.size
制限fielddata
メモリ使用量、特定のサイズ(2G
など)、占有メモリの割合(20%など)にすることもできます。
次のコマンドを使用して監視することもできます。
GET /_stats/fielddata
最後に、1回限りのロードフィールドがメモリ値を直接超えた場合はどうなりますか?電話を切る?したがって、esはこの状況を防ぐためにサーキットブレーカ(ヒューズメカニズム)を使用します。
内部チェック(タイプ、カーディナリティ、サイズなど)を通じてクエリに必要なメモリを見積もります。次に、ロードするように要求されたフィールドデータによって、フィールドデータの合計量がヒープの構成された比率を超えるかどうかを確認します。推定クエリサイズが制限を超えると、サーキットブレーカーがトリガーされ、クエリが中止され、例外が返されます。
indices.breaker.fielddata.limit fielddata level limit, the default is 60% of the heap indices.breaker.request.limit request level request limit, the default is 40% of the heap indices.breaker.total.limit guarantees the limit combined with the above two, the default heap is 70%
フィールドデータフィルタリング
メモリを節約するように設定することにより、フィールドデータの一部のみをロードできます。
“frequency”: { “min”: 0.01, “min_segment_size”: 500 }
このドキュメントの少なくとも1%に表示されるアイテムのみをロードします。
ドキュメントが500未満の段落は無視してください。
詳しくは公式サイトをご覧ください。
フィールドデータのプリロード
フィールドデータの読み込みは、デフォルトでは遅延読み込みです。 Elasticsearchが初めてフィールドにクエリを実行すると、このフィールドのすべてのセグメントの転置インデックスがメモリに完全に読み込まれるため、今後のクエリでパフォーマンスが向上します。
小さなインデックスセグメントの場合、このプロセスに必要な時間は無視できます。ただし、インデックスが数GBの場合、このプロセスには数秒かかる場合があります。 1秒未満の応答に慣れているユーザーにとって、数秒の一時停止を受け入れることは困難です。
この遅延ピークを解決するには、次の3つの方法があります。
1.フィールドデータをプリロードします。事前にロードするように設定します。
2.グローバルシリアル番号をプリロードします。グローバルディクショナリ(文字列フィールドとそれに対応するグローバルに一意のint値を格納する)と同様に、メモリ使用量を削減するためのロード最適化方法。これにより、int値のみがロードされ、ディクショナリ内の対応する文字列フィールドが検索されます。
3.キャッシュのウォームアップ。非推奨になりました。
総括する
比較 | DocValues | FieldData |
---|---|---|
作成時間 | 転置インデックスの作成タイミングに合わせてインデックスが作成されます | 検索時に時間内に作成、遅延読み込み |
場所を作成する | ディスク。反転行と同じで、luceneファイルに保存されます(ディスクにシリアル化されます)。 | |
Luceneファイル操作は、オペレーティングシステムのキャッシュに依存して管理します | JVMヒープ | |
利点 | ヒープメモリを占有しません | 追加のディスクリソースを消費しません |
不利益 | インデックスの速度を遅くし、追加のディスクリソースを占有します | ドキュメントが多すぎると、インスタント作成に時間がかかり、ヒープを占有しすぎます。 |
サポートデータ型 | 分析されていないフィールドに対応 | 分析されたフィールドの文字列(単語のセグメンテーション) |