es 3期 第20节-运用指标聚合快速统计数值
#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。
#### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性,任何企图直接替代严格事务性场景的应用项目都会失败!!!
##### 索引字段与属性都属于静态设置,若后期变更历史数据需要重建索引才可生效
##### 对历史数据无效!!!!
##### 一定要重建索引!!!!
#### 1、aggs聚合概念介绍
### 聚合概念介绍
## 1.前面学习的都是ES查询数据,俗称明细查询;聚合就是统计分析,基于明细数据深入统计,按照不同的业务需求维度
## 2.ClickHouse vs Elasticsearch
### 聚合底层存储
## 1.Doc_values:ES内部使用列式存储机制
## 2.OLTP/OLAP/HTAP
## 3.凡是row-based数据产品都不适合做数据分析
### 聚合执行过程
## 1.客户端发送聚合请求
## 2.协调节点分发聚合请求
## 3.协调节点合并聚合结果
## 4.协调节点返回聚合结果
## 5.MPP(大规模并行处理)执行过程
### 聚合类型划分
## metric 数值指标聚合统计
## bucket 分桶分组聚合统计
## pipeline 管道二次聚合统计
## Matrix(数值)矩阵计算聚合统计(划分到数值里面了)
#### 2、metric数值聚合实战
### Metric聚合函数
## 1:仅限多种类似数值统计
## 2:包括单值/多值
### 初体验聚合
## 聚合关键字
# Aggs
# 聚合层级限制支持多层级,
# 聚合便利
# 1.可查询明细数据、过滤数据
# 2.可分页查询
# 3.可返回总数
# 4.可聚合统计
# 查询统计
# 便利性体现在,一个查询语句可以拿到总数、行数据、统计数据,相对传统数据库来说要执行3次sql才能做到
GET kibana_sample_data_ecommerce/_search
{
// 从第0个开始返回明细
"from":0,
// 返回2个明细数据
"size":2,
// 返回总行数
"track_total_hits":true,
// 过滤条件
"query":{
"term": {
"day_of_week": {
"value": "Monday"
}
}
},
"aggs":{
"sum_taxful_total_price":{
// 总和
"sum": {
"field": "taxful_total_price"
}
}
}
}
### 常用指标聚合
## 数值统计
# 聚合函数Sum/max/min/avg/stats/extended_stats
# 单个值的数值统计
# 浮点数值统计精确性问题
# 注意 taxful_total_price字段是float类型,数据本身只有2为小数,统计后会产生多小数,这是因为es底层是java写的,java自带的问题
GET kibana_sample_data_ecommerce/_search
{
// size=0,明确表示不需要返回明细数据,好习惯
"size":0,
"track_total_hits":true,
"aggs":{
"sum_taxful_total_price":{
// 总和
"sum": {
"field": "taxful_total_price",
// 防止字段缺失或数据为null的情况,使用0填补
// 这是个好习惯(字段缺失对es来说不友好)
"missing": 0
}
},
"avg_taxful_total_price":{
// 平均值
"avg": {
"field": "taxful_total_price"
}
},
"max_taxful_total_price":{
// 最大值
"max": {
"field": "taxful_total_price"
}
},
"min_taxful_total_price":{
// 最小值
"min": {
"field": "taxful_total_price"
}
}
}
}
## stats 多种类型统计
# 查询结果里count、min、max、avg、sum都返回的
GET kibana_sample_data_ecommerce/_search
{
// size=0,明确表示不需要返回明细数据,好习惯
"size":0,
"track_total_hits":true,
"aggs":{
"stats_taxful_total_price":{
// 多种类型统计,查询结果里count、min、max、avg、sum都返回的
"stats": {
"field": "taxful_total_price",
// 防止字段缺失或数据为null的情况,使用0填补
// 这是个好习惯(字段缺失对es来说不友好)
"missing": 0
}
}
}
}
## extended_stats 类型统计
# 在stats扩展了更多的统计方式
GET kibana_sample_data_ecommerce/_search
{
// size=0,明确表示不需要返回明细数据,好习惯
"size":0,
"track_total_hits":true,
"aggs":{
"extended_stats_taxful_total_price":{
// 扩展多种类型统计
"extended_stats": {
"field": "taxful_total_price",
// 防止字段缺失或数据为null的情况,使用0填补
// 这是个好习惯(字段缺失对es来说不友好)
"missing": 0
}
}
}
}
### 百分比统计
# 聚合函数
# percetiles,计算数据的百分位占比,常见场景为计算响应时间的百分位数
## es 提供了两种不同的算法来计算百分位数:
# tdigest(默认):使用 T-Digest 算法,适合处理大数据集,能够在较小的内存占用下提供较高的精度。
# hdr:使用 HDR(High Dynamic Range)直方图算法,适合需要极高精度的场景,但可能会占用更多的内存。
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-aggregations-metrics-percentile-aggregation.html
# tdigest 和 hdr 算法都允许你通过 compression 参数来调整精度和内存占用之间的平衡。较大的 compression 值会提高精度,但也会增加内存消耗。
GET kibana_sample_data_ecommerce/_search
{
// size=0,明确表示不需要返回明细数据,好习惯
"size":0,
"track_total_hits":true,
"aggs":{
"percentiles_taxful_total_price":{
// 扩展多种类型统计,
"percentiles": {
"field": "taxful_total_price",
// percents 默认就是下面的百分比区间,可以不写,范围在0到100
"percents": [1, 5, 25, 50, 75, 95, 99],
// 不同的返回格式,默认true
"keyed":true,
"tdigest":{
// 默认100
"compression": 100
}
}
}
}
}
## 响应结果解释
# {
# "aggregations": {
# "percentiles_taxful_total_price": {
# "values": {
# "1.0": 21.984375, // 有 1% 的数据小于等于21.984375
# "5.0": 27.984375, // 有 5% 的数据小于等于27.984375
# "25.0": 44.96875, // 有 25% 的数据小于等于44.96875
# "50.0": 63.96875, // 有 50% 的数据小于等于63.96875
# "75.0": 93.03563731527095, // 有 75% 的数据小于等于93.03563731527095
# "95.0": 156, // 有 95% 的数据小于等于156
# "99.0": 222 // 有 99% 的数据小于等于222
# }
# }
# }
# }
## 使用hdr高精度的统计
# number_of_significant_value_digits 有效数字精度值,默认值3
# 较高的值:保留更多的有效数字,计算结果更精确,但可能会占用更多的内存和计算资源。
# 较低的值:保留较少的有效数字,计算结果的精度较低,但可以减少内存占用和提高性能。
GET kibana_sample_data_ecommerce/_search
{
// size=0,明确表示不需要返回明细数据,好习惯
"size":0,
"track_total_hits":true,
"aggs":{
"percentiles_taxful_total_price":{
// 扩展多种类型统计,
"percentiles": {
"field": "taxful_total_price",
"percents": [1, 5, 25, 50, 75, 95, 99],
"hdr": {
"number_of_significant_value_digits": 3
}
}
}
}
}
## percentile_ranks
# 根据提供的一个或多个具体值,返回这些值在数据集中的百分位位置
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"percentiles_ranks_taxful_total_price": {
"percentile_ranks": {
"field": "taxful_total_price",
"values": [50, 100, 200] // 要计算百分位排名的具体值
}
}
}
}
# 响应结果解析
# 应用场景,今年花费了了xxx元,打败了百分之多少的人
# {
# "aggregations": {
# "percentiles_ranks_taxful_total_price": {
# "values": {
# "50.0": 34.56951871657754, // 50这个值大约位于第 34.56951871657754 百分位
# "100.0": 79.31550802139039, // 100这个值大约位于第 79.31550802139039 百分位
# "200.0": 98.43850267379679 // 200这个值大约位于第 98.43850267379679 百分位
# }
# }
# }
# }
## cardinality 基数统计
# 聚合函数
# carintility:背后的算法Hyperloglog,该算法是非精确型的,默认3000个,ES最高支持40000个,超过了就是非精确型的
# 用于去重统计,如电商UV/PV
# precision_threshold 准确的阈值,默认3000,低于该计数预计将接近准确。超过这个值,计数可能会变得有点模糊。支持的最大值是40000
# https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"cardinality_customer_id": {
"cardinality": {
// 用户id维度去重,相当于uv
"field": "customer_id",
// 默认值3000
"precision_threshold": 3000
}
}
}
}
## value_count 字段值数量统计
# 数据值条数统计,没有去重
# 数值统计里面有多少条数据,当统计层级多的时候很有用
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"cardinality_customer_id": {
"value_count": {
// 用户id维度去重,相当于uv
"field": "customer_id"
}
}
}
}
## string_stats 字符串统计
# 聚合函数
# string_stats仅限keyword类型
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"string_stats_customer_full_name": {
"string_stats": {
"field": "customer_full_name.keyword"
}
}
}
}
### 脚本聚合
# 聚合函数
# Script
# 脚本能少用就少用,非必要不使用
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"avg_script_customer_full_name": {
"avg": {
"script": {
"source": """
doc['taxful_total_price'].value*10000;
"""
}
}
}
}
}
### 聚合分组明细数据
# 聚合函数
# top_hits,分组分桶查询时,设返回每组的top明细数据
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"my_customer_id": {
"terms": {
// 根据用户id聚合
"field": "customer_id",
// 返回10条
"size": 10
},
"aggs": {
"NAME": {
"top_hits": {
// 每个聚合结果里返回一条明细数据
"size": 1
}
}
}
}
}
}
### 头部指标聚合数据
# 聚合函数
# top_metrics
GET kibana_sample_data_ecommerce/_search
{
"size": 0,
"track_total_hits":true,
"aggs": {
"my_customer_id": {
"terms": {
// 根据用户id聚合
"field": "customer_id",
// 返回10条
"size": 10
},
"aggs": {
"NAME": {
"top_metrics": {
"metrics": [
{ "field": "taxful_total_price" } // 指定要提取的指标字段
],
"sort": [ // 指定排序条件
{ "taxful_total_price": {"order": "desc"}} // 按某个字段降序排序,返回值就是最大的
]
}
}
}
}
}
}
### 其它数据聚合
# 聚合函数Geo.xxx,地理位置聚合
# Weight AVG 权重指标聚合
#### 3、指标聚合建议与经验分享
## 聚合、明细查询、总数量
## 聚合与分片数量的关系(最好不要多个分片,但分片最好,es单分片支持<=65gb)
## 聚合列数数量与性能(同时统计多个指标看下对性能的影响)
## 聚合性能与缓存(希望聚合有缓存的话就每次都去查询同一个分片)
# 分片缓存
# 利用分片缓存,原则是尽量将查询分布在同一分片上,而不是利用ES自动选择分片的机制
# preference,分片选择参数,固定值local,或者固定分片编号
# GET kibana_sample_data_ecommerce/_search?preference=_local
## 聚合与浮点类型精确度
# 在数值聚合时,特别要注意 float与 double 类型,ES 是基于 Java 编写,会出现精度问题
# 尽量采用 long 类型或者其它数值类型来避免此精度问题
# ES 执行指标统计时底层采用 double 类型来构建,数值过长是基于近似,而非精确类型
## 聚合数值长度(最长支持long类型2的63次方)
# aggs 聚合
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-aggregations.html
# 指标聚合
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-aggregations-metrics.html
# top-hits 聚合明细
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-aggregations-metrics-top-hits-aggregation.html
# top-metrics 聚合明细数值
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/search-aggregations-metrics-top-metrics.html
# 分片缓存
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/shard-request-cache.html
# collapse 查询结果折看
# https://www.elastic.co/guide/en/elasticsearch/reference/8.6/collapse-search-results.html