重複排除後の数を数える
Elasticsearchによって提供される最初のおおよその集計は、 cardinality
(注:カーディナリティ)メトリックです。これは、フィールドのカーディナリティ、つまり、フィールドの個別の 値 または 一意の値の数を提供します 。あなたはSQLフォームに精通しているかもしれません:
車からCOUNT(DISTINCTカラー)を選択
重複排除は、多くの基本的なビジネス上の質問に答えることができる非常に一般的な操作です。
- ウェブサイトへのユニークな訪問者は何人ですか?
- 何台売られていますか?
- 毎月何人のユニークなユーザーが商品を購入していますか?
cardinality
メトリックを使用して、ディーラーが販売した車の色の数を決定できます 。
GET / cars / transactions / _search { "size":0、 "aggs":{ "distinct_colors":{ "cardinality":{ "field": "color" } } } }
Senseで表示するcURLとしてコピー
返された結果は、3つの異なる色の車が販売されたことを示しています。
... "aggregations":{ "distinct_colors":{ "value":3 } } .. ..
私たちの例をより便利にすることができます:毎月何台のカラーカーが販売されていますか?このメトリックを取得するにはcardinality
、1つのメトリックを 埋め込むだけで済みます date_histogram
。
GET / cars / transactions / _search { "size":0、 "aggs":{ "months":{ "date_histogram":{ "field": "sold"、 "interval": "month" }、 "aggs": { "distinct_colors":{ "cardinality":{ "field": "color" } } } } } }}
Senseで表示するcURLとしてコピー
計量することを学ぶ
この章の冒頭で述べたように、 cardinality
メトリックはおおよそのアルゴリズムです。これは、HyperLogLog ++ (HLL)アルゴリズムに基づいてい ます。HLLは最初に入力をハッシュし、次にハッシュ操作の結果のビットに基づいて確率を推定してベースを取得します。
技術的な詳細を理解する必要はありませんが(本当に興味がある場合は、このペーパーを読むことができます)、このアルゴリズムの特性に注意を払う必要があります 。
- 構成可能な精度。メモリ使用量を制御するために使用されます(精度が高い=メモリが多い)。
- 小さなデータセットの精度は非常に高いです。
- 構成パラメーターを使用して、重複排除に必要な固定メモリ使用量を設定できます。数千または数十億の一意の値に関係なく、メモリ使用量は構成の精度にのみ関係します。
精度を設定するにprecision_threshold
は、パラメータの値を指定する必要 があります。このしきい値は、ほぼ正確な結果を得ることを期待する基本レベルを定義します。次の例を考えてみましょう。
GET / cars / transactions / _search { "size":0、 "aggs":{ "distinct_colors":{ "cardinality":{ "field": "color"、 "precision_threshold":100 } } } }}
Senseで表示するcURLとしてコピー
|
|
この例では、フィールドの一意の値が100以内の場合に、非常に正確な結果が得られるようにします。アルゴリズムはこれを保証できませんが、カーディナリティがしきい値を下回っている場合、ほとんどの場合100%正しいです。しきい値を超えるベース番号は、精度を犠牲にしてメモリを節約し始め、測定結果にエラーをもたらします。
指定されたしきい値の場合、HLLデータ構造はおそらくprecision_threshold * 8
メモリのバイトを使用する ため、メモリの犠牲と追加の精度のバランスをとる必要があります。
実際のアプリケーションで 100
は、一意の値が100万であっても、しきい値はエラーを5%以内に維持できます。
速度の最適化
一意の値の数を取得する場合 は、通常 、データセット全体(またはほとんどすべてのデータ)をクエリする必要があります。すべてのデータに基づくすべての操作は高速でなければなりません。理由は明らかです。HyperLogLogの速度はすでに非常に高速で、データをハッシュし、いくつかのビット操作を実行するだけです。
しかし、速度が重要な場合は、さらに最適化することができます。HLLはフィールドコンテンツのハッシュ値のみを必要とするため、インデックス作成時に事前に計算できます。クエリ中にハッシュ計算をスキップして、フィールドデータから直接ハッシュ値をロードできます。
ハッシュ値の事前計算は、コンテンツが非常に長いかカーディナリティが高いフィールドでのみ役立ちます。これらのフィールドのハッシュ値を計算するコストは、クエリで無視できません。
数値フィールドのハッシュ計算は非常に高速ですが、元の値を保存するには、通常、同じ(またはそれ以下の)メモリスペースが必要です。これは、カーディナリティの低い文字列フィールドにも当てはまります。Elasticsearchの内部最適化により、一意の各値が1回だけハッシュされるようにすることができます。
基本的に、事前計算はすべてのフィールドが高速であることを保証するものではなく、カーディナリティが高いか、コンテンツが非常に長い文字列フィールドに対してのみ機能します。覚えておく必要があるのは、事前計算では、クエリに費やされた時間が事前にインデックスに転送されるだけであり、コストがかからないわけではありません。違いは、 インデックス作成中またはクエリ中にいつ実行するかを選択できることです 。
これを行うには、データに新しい複数値フィールドを追加する必要があります。最初にインデックスを削除し、ハッシュ値フィールドを含むマッピングを追加してから、インデックスを再作成します。
DELETE / cars / PUT / cars / { "mappings":{ "transactions":{ "properties":{ "color":{ "type": "string"、 "fields":{ "hash":{ "type" : "murmur3" }} } } } } } } POST / cars / transactions / _bulk {"index":{}} {"price":10000、 "color": "red"、 "make": "honda"、 "販売済み ":" 2014-10-28 "} {"インデックス ":{}} {"price":20000、 "color": "red"、 "make": "honda"、 "sold": "2014-11-05"} {"index":{}} {"価格":30000、 "色": "緑"、 "製造": "フォード"、 "販売": "2014-05-18"} {"インデックス":{}} {"価格":15000、 "color": "blue"、 "make": "toyota"、 "sold": "2014-07-02"} {"index":{}} {"price":12000、 "color": "green" 、 "make": "toyota"、 "sold": "2014-08-19"} {"index":{}} {"price":20000、 "color": "red"、 "make": "honda "、"販売済み ":" 2014-11-05 "} {"インデックス ":{}} {"価格 ":80000、"色 ":"赤 "、"make": "bmw"、 "sold": "2014-01-01"} {"index":{}} {"price":25000、 "color": "blue"、 "make": "ford" 、 "販売済み": "2014-02-12"}
Senseで表示するcURLとしてコピー
|
複数値フィールドのタイプは |
これで、集計を実行するときに、color.hash
フィールドの代わりに color
フィールドを使用し ます。
GET / cars / transactions / _search { "size":0、 "aggs":{ "distinct_colors":{ "cardinality":{ "field": "color.hash" } } } }}
Senseで表示するcURLとしてコピー
|
元のフィールドではなく、ハッシュされた複数値フィールドを指定することに注意してください。 |
これで、 cardinality
メトリックは"color.hash"
、元の値のハッシュを動的に計算する代わりに、(事前に計算されたハッシュ値)の値を読み取り ます。
1つのドキュメントで節約できる時間は非常に短いですが、1億のデータを集約し、各フィールドに10ナノ秒余分にかかる場合、クエリごとに1秒余分に追加されます。非常に大量のデータを使用する場合を使用すると cardinality
、事前計算を使用することの重要性、事前にハッシュを計算する必要があるかどうかを比較検討して、クエリのパフォーマンスを向上させることができます。いくつかのパフォーマンステストを実行して、事前計算されたハッシュがアプリケーションシナリオに適しているかどうかを確認します。。