一、聚合操作内部原理

1.正排索引(doc value)的聚合内部原理

①index-time生成

PUT/POST的时候,就会生成doc value数据,也就是正排索引

②核心原理与倒排索引类似

正排索引,也会写入磁盘文件中,然后os cache先进行缓存,以提升访问doc value正排索引的性能

如果os cache内存大小不足够放得下整个正排索引,doc value,就会将doc value的数据写入磁盘文件中

③性能问题:给jvm更少的内存,给os cache更大的内存

④如果的确不需要doc value,比如聚合等操作,那么可以禁用,减少磁盘空间占用

PUT my_index
{
  "mappings": {
 "my_type": {
   "properties": {
 "my_field": {
   "type":       "keyword"
   "doc_values": false 
 }
   }
 }
  }
}

⑤如果要对分词的field执行聚合操作,必须将fielddata设置为true

POST /test_index/_mapping/test_type 
{
  "properties": {
 "test_field": {
   "type": "text",
   "fielddata": true
 }
  }
}

二、易并行聚合算法:比如max

1.近似聚合算法

:采用在每个node上进行近估计的方式,得到最终的结论

如果采取近似估计的算法:延时在100ms左右,0.5%错误

如果采取100%精准的算法:延时一般在5s~几十s,甚至几十分钟,几小时,0%错误

2.三角选择原则

:精准+实时+大数据 --> 选择2个

a.精准+实时: 没有大数据,数据量很小,那么一般就是单击跑,随便你则么玩儿就可以

b.精准+大数据:hadoop,批处理,非实时,可以处理海量数据,保证精准,可能会跑几个小时

c.

大数据+实时

:es,不精准,近似估计,可能会有百分之几的错误率

三、cardinality去重算法

cartinality metric,对每个bucket中的指定的field进行去重,取去重后的count,类似于count(distcint)

cardinality,count(distinct),5%的错误率,性能在100ms左右

cardinality算法,会占用precision_threshold * 8 byte 内存消耗,100 * 8 = 800个字节

HyperLogLog++ (HLL)算法性能优化

例:GET /tvs/sales/_search

{

 "size" : 0,

 "aggs" : {

 "months" : {

"date_histogram": {

 "field": "sold_date",

 "interval": "month"

},

"aggs": {

 "distinct_colors" : {

 "cardinality" : {

"field" : "brand"

 }

 }

}

 }

 }

}

四、需求实战:记录下每次请求的访问的耗时,需要统计tp50,tp90,tp99

a.percentiles百分比算法

例:比如有一个网站,记录下了每次请求的访问的耗时,需要统计tp50,tp90,tp99

GET /website/logs/_search  
  
{ 
  
  "size": 0, 
  
  "aggs": { 
  
"group_by_province": { 
  
  "terms": { 
  
"field": "province" 
  
  }, 
  
  "aggs": { 
  
"latency_percentiles": { 
  
  "percentiles": { 
  
"field": "latency", 
  
"percents": [ 
  
  50, 
  
  95, 
  
  99 
  
] 
  
  } 
  
}, 
  
"latency_avg": { 
  
  "avg": { 
  
"field": "latency" 
  
  } 
  
} 
  
  } 
  
} 
  
  } 
  
}

b.percentile ranks和网站访问时延SLA统计

例:在200ms以内的,有百分之多少,在1000毫秒以内的有百分之多少

GET /website/logs/_search  
  
{ 
  
  "size": 0, 
  
  "aggs": { 
  
"group_by_province": { 
  
  "terms": { 
  
"field": "province" 
  
  }, 
  
  "aggs": { 
  
"latency_percentile_ranks": { 
  
  "percentile_ranks": { 
  
"field": "latency", 
  
"values": [ 
  
  200, 
  
  1000 
  
] 
  
  } 
  
} 
  
  } 
  
} 
  
  } 
  
}

c.percentile的优化:

TDigest算法:用很多节点来执行百分比的计算,近似估计,有误差,节点越多,越精准

compression:默认100,限制节点数量最多 compression * 20 = 2000个node去计算,越大,占用内存越多,越精准,性能越差,一个节点占用32字节,100 * 20 * 32 = 64KB,如果你想要percentile算法越精准,compression可以设置的越大

五、海量bucket优化机制:从深度优先到广度优先

例:对于评论数量排名前10的演员,每个演员的电影取到评论数量排名前5的电影

{ 
  
  "aggs" : { 
  
"actors" : { 
  
  "terms" : { 
  
 "field" :        "actors", 
  
 "size" :         10, 
  
 "collect_mode" : "breadth_first"  
  
  }, 
  
  "aggs" : { 
  
"costars" : { 
  
  "terms" : { 
  
"field" : "films", 
  
"size" :  5 
  
  } 
  
} 
  
  } 
  
} 
  
} 
  
}

深度优先的方式,构建了一整颗完整的树出来了,10万个actor,每个actor平均有10部电影,10万 + 100万 --> 110万的数据量的一颗树。构建了大量的数据,然后裁剪掉了99.99%的数据。

广度优先的方式,构建出film,裁剪出其中的5个film即可,10万 -> 50个