elasticsearch 聚合 : 指标聚合、桶聚合、管道聚合剖析使用总结 ...

打印 上一主题 下一主题

主题 1029|帖子 1029|积分 3087

❃博主首页 :   <码到三十五>   
  ☠博主专栏 :   <mysql高手>    <elasticsearch高手>    <源码解读>    <java焦点>    <口试攻关>   
  ♝博主的话 :  <搬的每块砖,皆为峰峦之基;公众号搜索(码到三十五)关注这个爱发技术干货的coder,一起筑基>   

  
一、聚合查询概述

Elasticsearch中的聚合查询是一种功能强大的数据分析工具,它可以或许提供从索引中提取和计算有关数据的复杂统计信息的能力。聚合查询不仅可以资助用户明白和分析数据中的趋势和模式,还能在业务决议中发挥关键作用。聚合查询支持多种类型,包括指标聚合、桶聚合和管道聚合,每一种都有其特定的应用场景和使用方法。
二、聚合查询类型


Metric Aggregations(指标聚合)



  • 概述:指标聚合返回基于字段值的度量效果,如总和、均匀值、最小值、最大值等。这些度量效果可以直接用于分析数据中的特定指标。
  • 常用类型:
    Sum:计算字段的总和。
    Avg:计算字段的均匀值。
    Min/Max:查找字段的最小值和最大值。
    Stats:提供包括count、sum、min、max和avg在内的多种统计信息。
  • 应用场景举例:销售数据的总销售额平静均订单金额分析、用户举动的均匀访问时长和最大访问深度分析等。

Bucket Aggregations(桶聚合)



  • 概述:桶聚合类似于SQL中的GROUP BY利用,它将文档分组到不同的桶中,并对每个桶中的文档举行聚合计算。桶聚合可以基于字段值、时间间隔或数值范围举行分组。
  • 常用类型:
    Terms:根据字段的值将文档分配到不同的桶中,常用于分析文本字段的不同取值及其分布情况。
    Date Histogram:根据日期字段的值,将文档按时间间隔(如天、周、月等)分组到桶中,实用于时间序列数据的分析。
    Range:根据界说的范围将文档分配到不同的桶中,实用于分析数值字段在特定范围内的文档数量。
  • 应用场景举例:按作者分组的博客文章数量统计、按月份统计的销售记录分析、按代价区间统计的产品数量等。

Pipeline Aggregations(管道聚合)



  • 概述:管道聚合以其他聚合的效果作为输入,并对其举行进一步的处置惩罚或计算。这种聚合类型允许用户对聚合效果举行复杂的转换和分析。
  • 常用类型:
    Avg Bucket:计算每个桶的均匀值,通常用于对分组数据举行均匀值分析。
    Sum Bucket:计算每个桶的总和,实用于对分组数据举行求和利用。
    Max/Min Bucket:找出所有桶中的最大值或最小值,有助于辨认分组数据中的极端情况。
  • 应用场景举例:在按月份统计的销售记录中找出均匀销售额最高的月份、分析不同代价区间产品的销售额总和等。

三、聚合查询应用



  • 与查询语句联合:聚合查询通常与查询语句联合使用,可以在满足特定条件的文档集合上举行聚合利用。通过查询语句过滤出符合条件的文档集合,然后对这些文档举行聚合分析,可以得到更加准确和有用的效果。
  • 嵌套聚合:Elasticsearch支持嵌套聚合,即在一个聚合内部可以包含其他聚合。通过嵌套聚合,用户可以构建复杂的查询和分析逻辑,满足各种复杂的数据分析和统计需求。
四、doc_values 与 fielddata

在 Elasticsearch 中,聚合利用重要依赖于 doc_values 或 fielddata 来举行。用于聚合的字段可以是精确值字段(如keyword类型)或分词字段(如text类型)。这两类字段在聚合查询时的处置惩罚方式有所不同。
exact value字段

精确值字段通常用于存储不须要分词和全文搜索的数据,如用户ID、产品类别等。对于这类字段,Elasticsearch默认使用doc_values数据结构来支持高效的聚合、排序和统计利用。doc_values以列式存储格式在磁盘上保存字段值,并在须要时加载到JVM堆内存中举行计算。由于doc_values直接在磁盘上利用,因此性能通常很高,且实用于大规模数据集。
分词字段

分词字段(如text类型)通常用于存储须要分词和全文搜索的文本数据。对于这类字段,Elasticsearch默认不启用fielddata,由于fielddata会将字段值加载到堆内存中,导致在处置惩罚大数据集时轻易引发内存溢出(OOM)问题。然而,偶然我们确实须要在分词字段上执行聚合利用(例如,按产品名称分组统计销售数据)。在这种情况下,有几种办理方案可供选择:

  • 使用.keyword子字段:在界说字段映射时,可以为text字段添加一个.keyword子字段。这个子字段不会被分词器处置惩罚,而是作为一个完整的字符串存储。通过使用该子字段举行聚合利用,可以得到更准确的效果,同时制止启用fielddata带来的性能问题。
  • 更新映射启用fielddata:如果你确实须要在text字段上启用fielddata(虽然不推荐),可以通过更新字段映射来实现。但请留意,如许做可能会导致内存斲丧过大,特殊是在处置惩罚大数据集时。因此,在启用fielddata之前,请务必评估其对系统性能的影响,并考虑其他可能的办理方案。
doc_values与fielddata的性能权衡

在Elasticsearch中,聚合利用重要依赖于doc_values或fielddata来访问文档中的字段值。相识这两种数据结构的差别和实用场景,有助于优化聚合查询的性能。
Doc Values



  • 优势:实用于精确值字段和数字类型字段,提供高效的聚合、排序和统计利用。由于直接在磁盘上利用,性能通常很高。
  • 实用场景:大多数精确值字段默认启用doc_values,无需额外设置。
Fielddata



  • 优势:支持复杂的文天职析和聚合利用,允许对分词字段举行聚合查询。
  • 劣势:须要占用大量堆内存资源,处置惩罚大数据集时轻易引发OOM问题。默认情况下,Elasticsearch禁用了对text字段的fielddata访问。
  • 实用场景:在确实须要在text字段上执行聚合查询,且系统资源允许的情况下,可以考虑启用fielddata。但请务必谨慎评估其对性能的影响。
总之, 对于精确值字段,利用doc_values可以得到高效且准确的聚合效果;对于分词字段,通过添加.keyword子字段或使用其他办理方案来制止启用fielddata带来的性能问题。通过合理设置字段映射和选择聚合查询策略,可以充实发挥Elasticsearch在数据分析范畴的强大功能。
五、multi-fields(多字段)



  • 形貌:在Elasticsearch中,一个字段可以被界说为multi-fields类型,这意味着同一份数据可以被索引为不同类型的字段。通过为text字段添加keyword子字段,用户可以在保留全文搜索功能的同时,为精确值搜索、排序和聚合利用提供支持。
  • 使用建议:对于须要举行聚合利用的text字段,猛烈建议在索引设计阶段添加keyword子字段,并使用该子字段举行聚合利用。如允许以制止在text字段上启用Fielddata带来的性能问题,并进步聚合查询的效率和准确性。
六、聚合查询示例

Terms 分桶聚合

示例场景:统计每个作者写了多少篇文章,并按文章数量降序排序。
查询语句:
  1. POST /blog/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "articles_per_author": {
  6.       "terms": {
  7.         "field": "author.keyword",
  8.         "size": 10,
  9.         "order": { "_count": "desc" }
  10.       }
  11.     }
  12.   }
  13. }
复制代码
Date Histogram 直方图聚合

示例场景:分析每月的销售记录数量。
查询语句:
  1. POST /sales/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_over_time": {
  6.       "date_histogram": {
  7.         "field": "sale_date",
  8.         "calendar_interval": "month",
  9.         "format": "yyyy-MM"
  10.       }
  11.     }
  12.   }
  13. }
复制代码
Range 范围聚合

示例场景:分析不同代价区间的产品数量。
查询语句:
  1. post /products/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "price_ranges": {
  6.       "range": {
  7.         "field": "price",
  8.         "ranges": [
  9.           { "to": 100 },
  10.           { "from": 100, "to": 500 },
  11.           { "from": 500 }
  12.         ]
  13.       }
  14.     }
  15.   }
  16. }
复制代码
Nested 嵌套聚合

示例场景:分析每个订单中不同产品的均匀代价。
假设数据:一个订单可以有多个产品,每个产品都有一个代价。
查询语句:
  1. POST /orders/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "orders": {
  6.       "nested": {
  7.         "path": "products"
  8.       },
  9.       "aggs": {
  10.         "avg_price_per_order": {
  11.           "avg": {
  12.             "field": "products.price"
  13.           }
  14.         }
  15.       }
  16.     }
  17.   }
  18. }
复制代码
Pipeline 管道聚合

示例场景:在按月份统计的销售记录中找出销售额最高的月份,并计算该月的均匀销售额。
查询语句:
  1. POST /sales/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_over_time": {
  6.       "date_histogram": {
  7.         "field": "sale_date",
  8.         "calendar_interval": "month"
  9.       },
  10.       "aggs": {
  11.         "total_sales": {
  12.           "sum": {
  13.             "field": "amount"
  14.           }
  15.         },
  16.         "top_sales_month": {
  17.           "top_hits": {
  18.             "sort": [
  19.               { "total_sales": { "order": "desc" } }
  20.             ],
  21.             "size": 1
  22.           }
  23.         },
  24.         "avg_sales_top_month": {
  25.           "avg_bucket": {
  26.             "buckets_path": "total_sales"
  27.           }
  28.         }
  29.       }
  30.     }
  31.   }
  32. }
复制代码
Derivative(导数聚合)

示例场景:分析销售数据的变化趋势,计算销售额的日增长率。
查询语句:
  1. POST /sales/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_over_time": {
  6.       "date_histogram": {
  7.         "field": "sale_date",
  8.         "calendar_interval": "day"
  9.       },
  10.       "aggs": {
  11.         "total_sales": {
  12.           "sum": {
  13.             "field": "amount"
  14.           }
  15.         },
  16.         "sales_derivative": {
  17.           "derivative": {
  18.             "buckets_path": "total_sales"
  19.           }
  20.         }
  21.       }
  22.     }
  23.   }
  24. }
复制代码
我们起首按天对销售数据举行分组,并计算天天的总销售额。然后,我们使用derivative管道聚合来计算销售额的日增长率。
Cumulative Sum(累计和聚合)

示例场景:计算销售数据的累计和,展示销售额的累计增长情况。
查询语句:
  1. POST  /sales/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_over_time": {
  6.       "date_histogram": {
  7.         "field": "sale_date",
  8.         "calendar_interval": "month"
  9.       },
  10.       "aggs": {
  11.         "total_sales": {
  12.           "sum": {
  13.             "field": "amount"
  14.           }
  15.         },
  16.         "cumulative_sales": {
  17.           "cumulative_sum": {
  18.             "buckets_path": "total_sales"
  19.           }
  20.         }
  21.       }
  22.     }
  23.   }
  24. }
复制代码
我们按月对销售数据举行分组,并计算每月的总销售额。然后,我们使用cumulative_sum管道聚合来计算销售额的累计和。
Moving Average(移动均匀聚合)

示例场景:分析销售数据的移动均匀线,以平滑数据波动并辨认趋势。
查询语句:
  1. POST /sales/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_over_time": {
  6.       "date_histogram": {
  7.         "field": "sale_date",
  8.         "calendar_interval": "day"
  9.       },
  10.       "aggs": {
  11.         "total_sales": {
  12.           "sum": {
  13.             "field": "amount"
  14.           }
  15.         },
  16.         "moving_avg_sales": {
  17.           "moving_avg": {
  18.             "buckets_path": "total_sales",
  19.             "window": 7  // 计算7天的移动平均
  20.           }
  21.         }
  22.       }
  23.     }
  24.   }
  25. }
复制代码
我们按天对销售数据举行分组,并计算天天的总销售额。然后,我们使用moving_avg管道聚合来计算7天的移动均匀销售额。
Bucket Script(桶脚本聚合)

示例场景:计算每个销售桶中不同产品的销售额占比。
查询语句(假设每个销售桶中按产品分组):
  1. POST  /sales/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_by_product": {
  6.       "terms": {
  7.         "field": "product.keyword"
  8.       },
  9.       "aggs": {
  10.         "total_sales": {
  11.           "sum": {
  12.             "field": "amount"
  13.           }
  14.         },
  15.         "sales_percentage": {
  16.           "bucket_script": {
  17.             "buckets_path": {
  18.               "thisSales": "total_sales",
  19.               "totalSales": "_sum"  // 假设外层还有一个求和聚合来计算总销售额
  20.             },
  21.             "script": "params.thisSales / params.totalSales * 100"
  22.           }
  23.         }
  24.       }
  25.     },
  26.     "total_sales": {
  27.       "sum": {
  28.         "field": "amount"
  29.       }
  30.     }
  31.   }
  32. }
复制代码
bucket_script引用了两个buckets_path,其中_sum是Elasticsearch中的一个特殊变量,它引用了当前聚合上下文中所有桶的总和。这个示例假设外层还有一个求和聚合来计算所有产品的销售总额。然后,我们计算每个产品销售额占总销售额的百分比。
Filters 过滤器聚合

示例场景:分析不同分类产品的销售情况。
查询语句:
  1. POST /products/_search
  2. {
  3.   "size": 0,
  4.   "aggs": {
  5.     "sales_by_category": {
  6.       "filters": {
  7.         "filters": {
  8.           "electronics": { "term": { "category": "electronics" }},
  9.           "books": { "term": { "category": "books" }},
  10.           "other": { "match_all": {} }
  11.         }
  12.       },
  13.       "aggs": {
  14.         "total_sales": {
  15.           "sum": {
  16.             "field": "price"
  17.           }
  18.         }
  19.       }
  20.     }
  21.   }
  22. }
复制代码
我们使用了filters聚合来按产品分类过滤文档,并在每个过滤器内部使用sum聚合来计算总销售额。
七、聚合排序



  • 基于count排序:通过聚合的_count字段对桶举行排序,可以展示销售量最高或最低的产品、访问量最大的网页等。
  • 基于key排序:对于Terms聚合,可以使用_key字段对桶的键(即分组字段的值)举行排序。这有助于按字母次序或数值次序展示分组数据。
八、优化建议



  • 制止不须要的大聚合:对于大数据集,执行复杂的聚合利用可能会斲丧大量计算资源并影响性能。因此,建议根据实际需求合理设计聚合查询,制止执行不须要的大聚合利用。
  • 缓存聚合效果:对于频仍执行的聚合查询,可以考虑使用Elasticsearch的缓存功能来缓存聚合效果。如允许以镌汰重复计算的开销并进步查询性能。
  • 合理设计索引和映射:根据查询需求和数据特点,合理设计索引和映射是优化聚合查询性能的关键。例如,选择得当的字段类型和属性、合理设置分片数和副本数等。
  • 监控和分析:定期监控和分析Elasticsearch的性能指标和日志可以资助及时发现息争决匿伏的性能问题。通过监控聚合查询的执行时间、内存使用情况等指标,可以评估聚合查询的性能并举行相应的优化调整。

    关注以下公众号获取更多深度内容,纯干货 !   


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

慢吞云雾缓吐愁

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表