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 给全部核心聚合函数标了类别:
| 类别 | 函数 | 合并方式 |
|---|---|---|
| Distributive | SUM、COUNT、MIN、MAX | 分片结果直接合并 |
| Algebraic | AVG、STDDEV、VARIANCE | 保留中间量套公式 |
| Holistic | MEDIAN、PERCENTILE、COUNT DISTINCT | 必须全量明细 |
| Sketch-based | APPROX_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_DISTINCT | HyperLogLog 近似去重 | 亿级行 UV 统计 | ~2% |
APPROX_PERCENTILE | t-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 标准 | Tableau | Looker Studio | DAX |
|---|---|---|---|
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),仅供参考