面试知识库
进阶

ES聚合查询#

一句话答案#

ES 聚合分 Bucket(分桶/分组)、Metric(指标计算)、Pipeline(二次计算)三类,可嵌套组合实现复杂数据分析;底层基于 doc_values 列式存储实现高效聚合,类似数据库的 GROUP BY + 聚合函数。

核心要点

聚合分类#

类型作用类比 SQL
Bucket按条件分桶GROUP BY
Metric计算指标SUM/AVG/MAX
Pipeline对聚合结果再计算子查询/窗口函数

Bucket 聚合(分桶)#

Metric 聚合(指标)#

{
  "aggs": {
    "avg_price": { "avg": { "field": "price" } },
    "max_price": { "max": { "field": "price" } },
    "total_sales": { "sum": { "field": "sales_count" } },
    "price_stats": { "stats": { "field": "price" } },
    "unique_brands": { "cardinality": { "field": "brand" } }
  }
}
json

嵌套聚合#

// 每个品牌的平均价格(Bucket + Metric 嵌套)
{
  "size": 0,
  "aggs": {
    "by_brand": {
      "terms": { "field": "brand", "size": 10 },
      "aggs": {
        "avg_price": { "avg": { "field": "price" } },
        "top_products": {
          "top_hits": { "size": 3, "_source": ["name", "price"] }
        }
      }
    }
  }
}
json

Pipeline 聚合#

// 每月销售额的环比增长率
{
  "aggs": {
    "monthly": {
      "date_histogram": { "field": "date", "calendar_interval": "month" },
      "aggs": {
        "total_sales": { "sum": { "field": "amount" } }
      }
    },
    "mom_growth": {
      "derivative": { "buckets_path": "monthly>total_sales" }
    }
  }
}
json

Doc Values(聚合性能基础)#

倒排索引:词项 → 文档列表(适合搜索)
Doc Values:文档 → 字段值(适合排序/聚合)

存储方式:列式存储(类似 Parquet)
  Doc1.price = 99
  Doc2.price = 199
  Doc3.price = 299

特点:
- 默认开启(除 text 类型外)
- 存在磁盘,通过 OS Page Cache 加速
- 不需要额外内存(对比 fielddata 需要大量 JVM 堆内存)
plaintext

聚合性能优化#

问题方案
聚合太慢加 filter 缩小聚合范围
高基数 terms用 composite 分页聚合
精确去重太慢cardinality 用 HyperLogLog(近似)
全量聚合预聚合(Rollup / Transform)
面试回答(2分钟版)

ES 聚合分三类:Bucket 聚合按条件分桶(类似 GROUP BY),比如按品牌、按价格区间、按月份分桶;Metric 聚合在桶内做计算(avg/sum/max/cardinality);Pipeline 聚合对聚合结果再计算(如环比增长率)。三者可以嵌套组合,比如”每个品牌的平均价格+top3商品”就是 terms → avg + top_hits 嵌套。性能基础是 doc_values 列式存储——和倒排索引互补,倒排索引按词项查文档(搜索),doc_values 按文档取字段值(排序/聚合)。优化方面:加 filter 缩小聚合范围、高基数字段用 composite 分页、精确去重用 cardinality(底层 HyperLogLog 有约 0.5% 误差)。

追问与易错

追问方向:

  • “text 字段能聚合吗?”→ 不能直接聚合(无 doc_values),需要开 fielddata(吃内存)或用 .keyword 子字段
  • “cardinality 精确吗?”→ 底层 HyperLogLog,有约 0.5% 误差,真需要精确用 script
  • “聚合和 SQL GROUP BY 区别?”→ ES 聚合可以多层嵌套、支持 Pipeline、实时分布式计算

易错点:

  • ❌ “聚合结果是精确的”——terms 聚合在分布式场景下有精度问题(每个 Shard 各自取 Top-N 再合并)
  • ❌ “size:0 不需要”——聚合时设 size:0 跳过 hits 返回,否则既查文档又做聚合
  • ❌ “聚合能代替 OLAP”——ES 聚合适合实时简单分析,复杂 BI 分析用 ClickHouse/Doris