ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Apache Ossie 聚合函数全解:为什么语义层的 MEDIAN 跑不动,而 SUM 秒出?

Apache Ossie 聚合函数全解:为什么语义层的 MEDIAN 跑不动,而 SUM 秒出?

Apache Ossie 聚合函数全解:为什么语义层的 MEDIAN 跑不动,而 SUM 秒出?

【免费下载链接】ossieApache Ossie, industry wide specification effort to standardize how we exchange semantic metadata across analytics, AI and BI platforms, providing a vendor neutral, single source of truth for semantic data项目地址: https://gitcode.com/GitHub_Trending/osi1/ossie

Apache Ossie 是 Apache 旗下的开源规范,用于在分析、AI 与 BI 平台之间交换语义元数据,做厂商中立的"单一事实来源"。同一个语义层,为什么SUM指标千万行秒出,MEDIAN指标一上亿级数据就超时?预聚合、多阶段聚合到底哪些指标能用?这两个问题的答案都藏在 Ossie 表达式语言的一个概念里:可分解性(Decomposability)。

1. 30 秒理解可分解性:分桶打水类比

先别背定义,打个比方。你要量出一池水的总量,三种函数是三种难度:

  • SUM:把池子分两半,各拿桶量完直接相加,零误差——这是Distributive(分布式);
  • AVG:两半各自算平均值没法直接平均(每半水量不同),得先记下"总和 + 份数"两个中间量,再套公式合并——这是Algebraic(代数式);
  • MEDIAN:把两半各自的中位数摆在一起,拼不出整体的中位数,必须看全量数据排完序——这是Holistic(整体式)。

说白了,可分解性回答的就是一个问题:这个指标能不能先分片算、再合并结果?它直接决定指标能否走预聚合、多阶段聚合和分布式查询。Ossie 给全部核心聚合函数标了类别:

类别函数合并方式
DistributiveSUM、COUNT、MIN、MAX分片结果直接合并
AlgebraicAVG、STDDEV、VARIANCE保留中间量套公式
HolisticMEDIAN、PERCENTILE、COUNT DISTINCT必须全量明细
Sketch-basedAPPROX_COUNT_DISTINCT 等草图结构可合并

Ossie 把语义模型分成三层:本体层语言还在定义中,逻辑层(指标、字段、过滤器所在层)用 Ossie SQL 表达式语言,物理层则是各数据库的原生 SQL。聚合函数就工作在中间这层,完整规范见 expression_language.md。

2. Ossie 表达式语言的聚合函数按用途怎么选

按场景分组比背函数名更实用。

2.1 日常必用

函数一句话说明典型场景可分解性
SUM(expr)求和销售额、成本汇总Distributive
COUNT(expr)/COUNT(*)非空计数 / 总行数订单量、行数统计Distributive
MIN/MAX最小 / 最大值首末时间、极值Distributive
AVG(expr)算术平均客单价类均值Algebraic
条件聚合CASE WHEN内嵌过滤只统计已完成订单随内层函数

条件聚合是必选支持的能力,写法是SUM(CASE WHEN status = 'completed' THEN amount ELSE 0 END)——过滤条件不进WHERE(表达式语言不支持WHERE),而是塞进CASE里。

2.2 精确统计

函数一句话说明典型场景可分解性
STDDEV/VARIANCE样本标准差 / 方差波动、离散度分析Algebraic
STDDEV_POP/VAR_POP总体版本全量数据描述Algebraic
MEDIAN(expr)中位数抗极值中心值Holistic
PERCENTILE_CONT/_DISC连续(插值)/ 离散分位数P95、分位监控Holistic

分位数语法是PERCENTILE_CONT(p) WITHIN GROUP (ORDER BY expr),p取 0~1,0.75 就是第 75 百分位。

2.3 性能救星

函数一句话说明典型场景误差
APPROX_COUNT_DISTINCTHyperLogLog 近似去重亿级行 UV 统计~2%
APPROX_PERCENTILEt-digest 近似分位数P95 响应时间~1%

近似聚合是 RECOMMENDED 级别,基于概率草图(sketches),草图结构本身可合并,天生适配分布式。注意 BigQuery 的写法是APPROX_QUANTILES(expr, 100)[OFFSET(75)],PostgreSQL 无原生支持——这些差异靠第 3 节的方言机制吸收。

3. 实战:TPC-DS 示例模型里的指标写法

仓库自带的 tpcds_semantic_model.yaml 演示了模型级指标,几个典型写法:

metrics: - name: customer_lifetime_value expression: dialects: - dialect: ANSI_SQL expression: >- SUM(store_sales.ss_ext_sales_price) / COUNT(DISTINCT customer.c_customer_sk) - name: store_productivity expression: dialects: - dialect: ANSI_SQL expression: >- SUM(store_sales.ss_ext_sales_price) / NULLIF(SUM(store.s_number_employees), 0)

第一段在做什么:跨两个数据集的复合指标,分子是 Distributive 的SUM,分母是 Holistic 的COUNT(DISTINCT ...),整体按最严格的一方算——预聚合收益有限,这就是"客单价"类指标难优化的原因。第二段用NULLIF(x, 0)把分母为 0 的情况转成 NULL 防除零,写比率指标时的防御性习惯。同一个指标还可以在dialects数组里并列多个方言版本,例如 BigQuery 的DATE_TRUNC(d, MONTH)与 ANSI 的DATE_TRUNC('month', d)参数顺序相反,各自写一份,实现按方言选用,同一模型在多引擎上都能跑通。指标字段的完整定义(含datatype、ai_context同义词)见 spec.md 的 Metrics 章节。

4. 从 Tableau / DAX 迁移:函数写法映射

Ossie 标准TableauLooker StudioDAX
COUNT(DISTINCT x)COUNTD(x)COUNT_DISTINCT(X)DISTINCTCOUNTNOBLANK(x)
AVG(x)AVG(x)AVG(X)AVERAGE(x)
VARIANCE(x)VAR(x)VARIANCE(X)VAR.S(x)
MEDIAN(x)MEDIAN(x)MEDIAN(X)MEDIAN(x)
PERCENTILE_CONT(0.75)PERCENTILE(x, 0.75)PERCENTILE(X, 75)PERCENTILE.INC(x, 0.75)

这里有个坑:DAX 把 BLANK 也算一个去重值,SQL 则排除 NULL,同一列两边COUNT(DISTINCT)会差 1,规范特意把它映射到DISTINCTCOUNTNOBLANK;另外空集上 SQL 计数返回 0,DAX 返回 BLANK。从 DAX 迁移指标时,去重计数和空值行为两处要逐条核对,完整映射表在 expression_language.md 的 Cross-Reference 章节。

5. 记住这三点就够了

① 选聚合函数先看可分解性:Distributive 能直接预聚合,Algebraic 要带"总和 + 计数"类中间量,Holistic 只能全量算——指标跑不动时先查它属于哪类。

② 写比率指标用NULLIF包分母防除零;亿级数据上的精确去重和分位数,优先换成APPROX_COUNT_DISTINCT/APPROX_PERCENTILE,用 1%~2% 误差换数量级的提速。

③ 方言差异交给dialects机制:核心函数写 ANSI 语义,各引擎的怪癖在方言条目里各写一份,别把数据库特性焊死进指标定义。

下一步建议:拿 examples/tpcds_semantic_model.yaml 做模板,配合validation/目录下的校验脚本(validate.py)验证自己写的语义模型,改完指标跑一遍校验最踏实。

【免费下载链接】ossieApache Ossie, industry wide specification effort to standardize how we exchange semantic metadata across analytics, AI and BI platforms, providing a vendor neutral, single source of truth for semantic data项目地址: https://gitcode.com/GitHub_Trending/osi1/ossie

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进