预聚合能力参考
本文说明 Foggy Java 引擎中的预聚合能力。该能力已有模型定义、匹配、SQL 改写和测试覆盖,但在具体项目中是否启用,应结合真实数据规模、刷新链路、查询口径和性能收益做项目级验证。预聚合是查询性能优化能力,不改变 TM/QM 的字段语义,也不是 MCP 工具协议的一部分。
1. 能力定位
preAggregations 用于在 TM 上声明已经存在或可被刷新任务生成的预计算聚合表。查询执行时,引擎会根据当前查询的维度、时间粒度、指标、过滤条件和运行时配置,判断是否可以把原始聚合查询改写到预聚合表上执行。
在完成项目级验证后,它适合以下场景:
- 高频聚合分析,例如按天、按月、按客户、按商品分类汇总。
- 大事实表上的常用指标查询。
- 可以接受预计算刷新周期的数据看板或 AI 分析入口。
- 查询结果需要保留原有 QM 字段语义,但希望降低原始表扫描成本。
它不适合替代完整的语义建模,也不应默认对所有查询开启。字段是否可查询仍由 QM 决定;预聚合只决定一次查询能否走更快的物理执行路径。
2. 使用状态口径
公开文档中应按以下口径理解预聚合:
| 层面 | 状态 |
|---|---|
| 引擎实现 | Java 引擎包含预聚合定义加载、匹配、SQL 改写、rollup、hybrid 和 returnTotal 聚合路径 |
| 自动刷新 | 存在独立 add-on,可生成 DDL 和全量/增量刷新 SQL,并提供刷新服务入口 |
| 测试覆盖 | 已有匹配、集成、数据一致性、边界场景和刷新 SQL 生成相关测试 |
| 项目实践 | 需要在目标项目中结合真实业务模型、数据量、刷新策略和查询证据单独验证 |
因此,预聚合在当前文档中定位为“高级可选优化能力”,而不是默认查询路径或核心语义层契约。
3. 与 TM/QM/DSL 的关系
| 层级 | 作用 |
|---|---|
| TM | 声明物理表、字段、维度、指标,以及可选的 preAggregations 元数据 |
| QM | 决定哪些字段对查询调用方可见 |
| JSON Query DSL | 按 QM 暴露字段提交查询请求 |
| 预聚合匹配器 | 判断当前 DSL 查询生成的聚合计划是否可由某张预聚合表满足 |
| SQL 改写器 | 在命中时把查询 SQL 改写到预聚合表 |
调用方不需要在 DSL 中显式指定预聚合表。是否命中预聚合由引擎根据模型定义和运行时配置决定。
4. 基本定义
preAggregations: [
{
name: 'dailyProductSales',
caption: '每日商品销售预聚合',
tableName: 'preagg_daily_product_sales',
priority: 80,
dimensions: ['salesDate', 'product'],
granularity: {
salesDate: 'day'
},
dimensionProperties: {
product: ['caption', 'categoryName', 'brand']
},
measures: [
{ name: 'salesAmount', aggregation: 'sum', columnName: 'sales_amount' },
{ name: 'quantity', aggregation: 'sum', columnName: 'quantity' },
{ name: 'orderCount', aggregation: 'count', columnName: 'order_count' }
],
refresh: {
strategy: 'INCREMENTAL',
watermarkColumn: 'salesDate$id',
lookbackDays: 1
},
enabled: true
}
]4.1 顶层属性
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 预聚合定义名称 |
caption | string | 否 | 显示名称 |
tableName | string | 是 | 预聚合物理表名 |
schema | string | 否 | 预聚合表 schema |
priority | number | 否 | 匹配优先级,数值越高越优先 |
dimensions | string[] | 否 | 预聚合表覆盖的维度 |
granularity | object | 否 | 时间维度粒度映射 |
dimensionProperties | object | 否 | 预聚合表覆盖的维度属性 |
dimensionPropertyColumnNames | object | 否 | 维度属性到预聚合表物理列的映射 |
measures | array | 否 | 预聚合表覆盖的指标 |
filters | array | 否 | 预聚合表内置过滤条件元数据 |
refresh | object | 否 | 刷新策略元数据 |
enabled | boolean | 否 | 是否启用,默认启用 |
4.2 指标属性
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
name | string | 是 | 对应 TM/QM 指标名 |
aggregation | string | 是 | 预聚合列所代表的聚合方式 |
columnName | string | 否 | 预聚合表中的物理列名 |
当前匹配逻辑主要覆盖 sum、count、min、max 等可安全 rollup 的聚合。avg 需要 sum + count 才能稳定上卷,当前不应作为预聚合 rollup 的默认假设。
4.3 刷新属性
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
strategy | string | 否 | 刷新策略,常见值为 FULL、INCREMENTAL |
schedule | string | 否 | 调度表达式或宿主约定的调度标识 |
watermarkColumn | string | 否 | 增量刷新或 hybrid 查询使用的水位字段 |
lookbackDays | number | 否 | 增量刷新回看天数 |
刷新元数据本身不会让表自动存在。实际项目需要由工程侧创建预聚合表,并通过刷新任务、调度服务或外部数据作业维护其中的数据。
5. 匹配规则
预聚合命中需要同时满足以下条件:
| 条件 | 规则 |
|---|---|
| 查询类型 | 主要面向有维度和指标的聚合查询 |
| 维度 | 查询维度必须是预聚合维度的子集 |
| 维度属性 | 查询使用的维度属性必须被预聚合覆盖;id、caption 存在部分隐式映射规则 |
| 时间粒度 | 查询粒度不能比预聚合粒度更细,例如日预聚合可以上卷到月,月预聚合不能回答日查询 |
| 指标 | 查询指标必须被预聚合覆盖 |
| 聚合方式 | 查询聚合方式必须与预聚合列兼容 |
| slice 条件 | 过滤字段需要能映射到预聚合表字段 |
| 自定义 SQL | 包含自定义 SQL 条件的查询不会命中预聚合 |
| 启用状态 | enabled: false 的预聚合不会参与匹配 |
当多张预聚合表都可满足查询时,引擎会结合 priority、维度覆盖差异和粒度差异选择更合适的表。
6. 执行模式
| 模式 | 说明 |
|---|---|
direct | 查询粒度和字段集合可直接由预聚合表满足 |
rollup | 预聚合表粒度更细,引擎在预聚合结果上继续聚合 |
hybrid | 预聚合数据覆盖历史区间,源表补充水位线之后的新数据 |
hybrid 查询依赖水位字段和运行时配置,默认不应假定开启。开启后仍需要验证水位线、刷新周期和源表补偿区间是否符合业务口径。
7. 查询证据
命中预聚合后,执行上下文会记录预聚合使用情况。宿主系统可以在查询证据或调试信息中暴露这些字段:
| 字段 | 说明 |
|---|---|
preAggUsed | 使用的预聚合名称 |
preAggMode | 命中模式,如 direct、rollup、hybrid |
preAggNeedsRollup | 是否需要在预聚合表上继续上卷 |
preAggAggregateUsed | returnTotal 聚合查询是否使用预聚合 |
这些字段用于解释查询计划和排查性能问题,不应被当作业务结果正确性的唯一证明。重要分析仍应结合源记录、SQL/DSL 证据和业务口径复核。
8. 刷新与维护
Foggy Java 项目中存在独立的预聚合 add-on,用于生成预聚合表 DDL、全量刷新 SQL、增量刷新 SQL,并提供刷新服务、调度和管理接口。该能力通常由宿主系统按部署环境接入。
项目中可以按两类方式维护预聚合表:
- 外部数据作业维护:由数仓、ETL、定时 SQL 或业务系统自行生成预聚合表。
- Foggy 预聚合 add-on 维护:由 add-on 根据模型定义生成刷新 SQL 并执行全量或增量刷新。
复杂维度属性、跨表属性、特殊方言 SQL 和事务边界需要在目标运行时验证。预聚合刷新链路属于工程集成能力,不应只依赖模型文件声明。
9. 当前边界
- 明细查询通常不会命中预聚合。
- 只有指标、没有分组维度的查询一般不作为主查询命中预聚合;
returnTotal聚合路径可能单独使用预聚合。 - 跨 TM 或复杂 JOIN 查询的预聚合匹配较保守,通常要求查询字段能由同一预聚合表覆盖。
- 自定义 SQL 条件会使预聚合匹配失败。
avg类指标不应默认依赖预聚合上卷。filters字段可作为预聚合元数据声明,但生产使用前应验证内置过滤条件与查询过滤条件的兼容性。- 预聚合表的数据新鲜度由刷新机制和水位线维护,不由 DSL 查询本身保证。
- 如果目标项目尚未实践预聚合,应先作为性能优化候选项验证,不应写入必须依赖预聚合的业务流程。
10. 建模建议
- 先根据真实高频查询选择预聚合维度,不要为所有维度组合建表。
- 时间维度优先从细粒度开始评估,例如日粒度可以服务月、季度等上卷分析。
- 只放入常用且可稳定聚合的指标。
- 维度属性只放入查询、过滤或展示中确实需要的字段。
- 为常用预聚合设置更高
priority,但仍应通过查询证据验证实际命中情况。 - 在上线前分别验证命中查询和未命中查询,确保未命中时能回退到原始查询路径。
