# cardinality 算法内存优化、hll 算法
# cardinality 算法内存优化
cardinality 5% 的错误率,性能在 100ms 左右
上面这句话是否是感觉很没有安全感?缺少一些重要的信息,比如是怎么计算来的?那么这会带出来一个配置参数 precision_threshold
GET /tvs/sales/_search { "size" : 0, "aggs" : { "distinct_brand" : { "cardinality" : { "field" : "brand", "precision_threshold" : 100 } } } }
Copied!
2
3
4
5
6
7
8
9
10
11
12
precision_threshold:在多少个 unique value 以内 cardinality 几乎保证 100% 准确, 默认值为 100,它的配置可以优化准确率和内存开销
怎么理解这个 100 个 unique value?
考虑一个场景:brand 去重,如果 brand 的 unique value 在100个以内,比如小米,长虹,三星,TCL,HTL ... 在去重后的结果在 100 个以内
cardinality 算法会占用 precision_threshold * 8 byte 内存消耗,100 * 8 = 800 个字节, 占用内存很小。而且 unique value 如果的确在值以内,那么可以确保 100% 准确 官方给的一个说法是 100,在数百万的 unique value 内错误率在 5% 以内
WARNING
反正我是有点懵逼,解说 precision_threshold 表示的是 多少个 unique value , 现在又说官网设置为 100,可以保证数百万
precision_threshold 值设置的越大,占用内存越大,1000 * 8 = 8000 / 1000 = 8KB,可以确保更多 unique value 的场景下 100% 的准确
field 去重 count,这时候 unique value 10000,precision_threshold=10000,10000 * 8 = 80000个byte,80KB
# HyperLogLog++(HLL)算法性能优化
cardinality 底层算法:使用 HLL 算法,优化 HLL 算法的性能即可
HLL 会对所有的 uqniue value 取 hash 值,通过 hash 值近似去求 distcint count,所以有一定误差
默认情况下,发送一个 cardinality 请求的时候,会动态地对所有的 field value,取 hash 值;
我们只要将取 hash 值的操作,前移到建立索引的时候,就能优化这个聚合性能了
PUT /tvs/ { "mappings": { "sales": { "properties": { "brand": { "type": "text", "fields": { "hash": { "type": "murmur3" } } } } } } } 手动内置 mapping hash 字段 GET /tvs/sales/_search { "size" : 0, "aggs" : { "distinct_brand" : { "cardinality" : { "field" : "brand.hash", "precision_threshold" : 100 } } } }
Copied!
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33