首页 / 聚合
APPROX_COUNT_DISTINCT 近似去重计数
APPROX_COUNT_DISTINCT 用 HyperLogLog 等算法估算去重个数,比 COUNT(DISTINCT) 省内存。Hologres、StarRocks、Doris 和 Spark 同名可用,MaxCompute 叫 APPROX_DISTINCT,Hive 和 Flink 没有内置的近似去重函数,只能用精确的 COUNT(DISTINCT)。
各引擎写法
| 引擎 | 支持 | 写法 | 说明 | 依据 |
|---|---|---|---|---|
| MaxCompute | 别名 | APPROX_DISTINCT(colname) | MaxCompute 2.0 扩展函数,返回 BIGINT,文档写明会有 5% 的误差。 | 官方文档 |
| Hologres | 支持 | APPROX_COUNT_DISTINCT(column) | 基于 HyperLogLog,平均误差 0.1%~1%。精度由 hg_experimental_approx_count_distinct_precision 控制,取值 12~20,默认 17。精确去重也可以用 UNIQ,它在带 GROUP BY 时比 COUNT DISTINCT 快。 | 官方文档 |
| StarRocks | 支持 | APPROX_COUNT_DISTINCT(expr) | 结果近似于 COUNT(DISTINCT col),使用固定大小的内存,适合高基数列。 | 官方文档 |
| Doris | 支持 | APPROX_COUNT_DISTINCT(expr) | 别名是 NDV。基于 HyperLogLog,只统计非 NULL 值,返回 BIGINT。 | 官方文档 |
| Hive | 需改写 | COUNT(DISTINCT col) | 内置函数文档中没有近似去重函数,只能用精确的 COUNT(DISTINCT)。 | 官方文档 |
| Spark SQL | 支持 | approx_count_distinct(expr[, relativeSD]) | Spark 1.6.0 起提供,基于 HyperLogLog++。relativeSD 是允许的最大相对标准差。 | 官方文档 |
| Flink SQL | 需改写 | COUNT(DISTINCT expr) | 内置函数文档中没有近似去重函数,只能用精确的 COUNT(DISTINCT)。 | 官方文档 |
迁移注意事项
- 各引擎的误差不同:MaxCompute 文档写的是 5%,Hologres 默认是 0.1%~1%。迁移后与原报表对数时,小的差异属于正常现象,不能直接当作数据问题。
- 近似结果不适合对账、计费这类要求精确的场景。这类指标应该用 COUNT(DISTINCT),或者用 Bitmap 做精确去重。
- 改写成 Hive 或 Flink 的 COUNT(DISTINCT) 后结果是精确值,但资源消耗会明显变大,大数据量下要评估内存和运行时间。
- Spark 的第二个参数 relativeSD 在其他引擎中没有对应写法,迁移时要去掉,并按目标引擎的方式调整精度,例如 Hologres 的会话参数。
示例
按天估算访问用户数
SELECT dt, APPROX_DISTINCT(user_id) AS uv FROM visits GROUP BY dt;SELECT dt, APPROX_COUNT_DISTINCT(user_id) AS uv FROM visits GROUP BY dt;SELECT dt, APPROX_COUNT_DISTINCT(user_id) AS uv FROM visits GROUP BY dt;SELECT dt, APPROX_COUNT_DISTINCT(user_id) AS uv FROM visits GROUP BY dt;SELECT dt, COUNT(DISTINCT user_id) AS uv FROM visits GROUP BY dt;SELECT dt, approx_count_distinct(user_id) AS uv FROM visits GROUP BY dt;SELECT dt, COUNT(DISTINCT user_id) AS uv FROM visits GROUP BY dt;