首页/数据/NoSQL 速查/cardinality 基数聚合(去重计数)
Elasticsearch89 条

cardinality 基数聚合(去重计数)

cardinality 聚合估算字段的不同值个数(类似 count distinct),内部使用 HyperLogLog++,结果近似;precision_threshold 越高越准但内存消耗上升。

NoSQL 速查数据更新于 2026-10-13

cardinality 做什么

cardinality 聚合用来估算某个字段有多少个不同取值,相当于 SQL 里的去重计数。它内部使用 HyperLogLog++ 做近似计算,用很小的内存就能处理很大的基数;precision_threshold 参数越高结果越准,内存开销也随之上升。

基本信息

接口"cardinality": { "field": "user_id" }
精度参数precision_threshold 默认 3000,上限 40000
精确性基数低于阈值时结果通常精确,超过阈值后误差随基数上升
字段要求应使用 keyword 或数值字段,text 字段需要 fielddata 才能聚合
组合用法可放进 terms 分桶,统计每个桶内的去重数量

典型使用场景

  • 统计独立用户数、独立 IP 等去重指标
  • 监控看板里的去重维度,对误差不敏感时最合适
  • 按分桶统计:每个地区有多少活跃用户
  • 粗略估算字段基数,判断它是否适合作为聚合维度
  • 验证字段基数是否足够低,为低基数编码之类的优化提供依据

常用写法

常用写法
# 全量去重用户数
GET /logs/_search
{ "size": 0, "aggs": { "unique_users": {
    "cardinality": { "field": "user_id", "precision_threshold": 40000 } } } }

# 按分桶统计去重数量
GET /logs/_search
{ "size": 0, "aggs": { "by_region": { "terms": { "field": "region", "size": 10 },
    "aggs": { "uv": { "cardinality": { "field": "user_id" } } } } } }

# 缺失值统一计数,避免漏算
GET /logs/_search
{ "size": 0, "aggs": { "uv": { "cardinality": { "field": "user_id", "missing": "unknown" } } } }

# 小基数时与精确计数对比,验证误差
GET /logs/_count
{ "query": { "term": { "user_id": "u1" } } }

参数与取舍

参数作用注意
field要去重统计的字段字段类型不匹配会直接报错
precision_threshold精度阈值,默认 3000 上限 40000调高更准但内存占用上升
missing给缺失字段的统一取值不设置时缺失值不计入
script用脚本动态取值更灵活但开销更高
基数小于精度阈值时结果通常是精确的,远超阈值时误差随基数增大。监控看板场景一般够用,计费与对账类场景要先做误差验证再决定是否采用。
cardinality 先在每个分片各自估算、再合并到协调节点,分片多时误差会叠加;需要更稳定的结果时可以先按时间范围缩小数据,或对同一个查询用不同精度阈值跑两轮做交叉验证。

易错点

  • 把 cardinality 当成精确的去重计数使用会踩坑,计费与对账类场景必须先验证误差范围
  • 对 text 字段做 cardinality 同样受 fielddata 限制,应改用 keyword 子字段,否则可能因内存超限导致查询失败
  • 把 precision_threshold 拉到上限就以为得到精确值:它只提高准确率,极端基数下依然存在误差
  • 在超大索引上对高基数字段做去重计数,内存占用虽小但需要读取该列的全部数据,耗时可能远超预期

数据来源与参考

  • Elasticsearch Guide: Cardinality aggregation
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌