1. 预聚合模型概述:什么是预聚合、为什么需要预聚合、预聚合的典型应用场景

大家好,我是你们这趟预聚合之旅的向导。今天咱们先聊聊最基础的问题——预聚合到底是什么?

说白了,预聚合就是「提前算好」。你想想看,如果每次查报表都要从头扫描几亿行数据,那得等到什么时候?预聚合的思路很简单:在数据写入的时候,或者定期跑批的时候,先把常用的汇总结果算好存起来。查询的时候直接拿结果,不用再现场算一遍。

核心定义:预聚合(Pre-Aggregation)是一种通过预先计算并存储聚合结果,来加速查询响应的技术手段。它用「存储空间」换「查询时间」。

1.1 为什么需要预聚合?

我刚开始做数仓那会儿,遇到过一件特别尴尬的事。业务方跑一张月度销售报表,SQL 写得很简单,就是 SUM(sales) GROUP BY month。但底层表有 5 亿行,每次跑都要 40 多秒。业务方天天抱怨:「你们这数据平台怎么比 Excel 还慢?」

后来我做了个预聚合表,把按月汇总的结果提前算好。查询时间直接从 40 秒降到了 0.2 秒。嗯,这就是预聚合的价值。

具体来说,预聚合解决了三个核心痛点:

  • 查询延迟高——原始数据量太大,每次聚合都要全表扫描,IO 和 CPU 都扛不住
  • 并发能力差——一个慢查询就把资源吃光了,其他人只能排队等
  • 计算成本贵——每次查询都重复计算同样的聚合,浪费算力

我的经验:判断一个场景是否需要预聚合,有个简单标准——如果同一个聚合查询每天被跑超过 3 次,就值得做预聚合。我曾经帮一个客户优化过,他们有个报表每天被 200 多人看,每次都要跑 2 分钟。做了预聚合之后,查询时间降到 0.5 秒,数据库 CPU 使用率从 85% 降到了 15%。

1.2 预聚合的典型应用场景

预聚合不是银弹,但它确实在几个场景里特别好用。我按自己的经验排了个序:

场景 典型查询 数据量级 预聚合效果
OLAP 多维分析 按时间、地区、产品维度汇总 亿级 ~ 百亿级 从分钟级降到秒级
实时数仓 最近 5 分钟的 PV/UV 千万级/天 从秒级降到毫秒级
BI 报表 月度 KPI、年度趋势 亿级 ~ 千亿级 从小时级降到秒级
监控大屏 实时指标、告警统计 百万级/分钟 从秒级降到亚秒级

OLAP 多维分析

这是预聚合最经典的战场。你想想看,一个电商平台每天产生几千万条订单数据。分析师要按「年-月-日-小时」看销售额,还要按「品类-品牌-SKU」下钻。如果每次都从原始数据算,那服务器得冒烟。

我参与过一个项目,用的是 Apache Kylin。我们把常用的维度组合(比如「时间+地区」、「时间+品类」)提前算好,存成 Cube。查询的时候直接命中预聚合结果,响应时间基本都在 1 秒以内。业务方反馈说:「终于不用等报表等到下班了。」

实时数仓

实时场景对延迟更敏感。我记得有一次帮一个直播平台做实时大屏,要求展示「最近 5 分钟的送礼金额 Top10 主播」。原始数据是 Kafka 流,每秒进来几万条。如果每条查询都去扫 Kafka 或者实时计算引擎,延迟根本控不住。

我们的做法是:用 Flink 做窗口聚合,每 10 秒算一次 Top10,结果写入 Redis。大屏直接读 Redis,延迟控制在 50 毫秒以内。这就是典型的实时预聚合。

避坑指南:我曾经犯过一个错误——在实时场景里把预聚合窗口设得太小(1 秒),结果预聚合本身成了性能瓶颈。后来调整为 10 秒窗口 + 增量更新,才把问题解决。实时预聚合的窗口大小,一定要根据业务容忍度和系统吞吐量来权衡。

BI 报表

BI 报表是预聚合的「舒适区」。大多数 BI 工具(如 Tableau、Superset、Metabase)都支持物化视图或者聚合表。你只需要在底层建好预聚合模型,前端查询自动命中。

我见过最夸张的一个案例:某金融公司有张 200 亿行的交易流水表,业务方每天要看「各分行当日交易额排名」。原始查询要跑 40 分钟,业务方每天早上开会前都要催一遍。后来我们建了按「分行+日期」的预聚合表,查询时间降到 3 秒。业务方说:「终于能在开会前看到数据了。」

1.3 预聚合的核心逻辑

说了这么多,咱们用一张图来总结预聚合的核心逻辑。这张图我画了很多次,每次培训新人都从它开始:

预聚合核心逻辑 原始数据 亿级 ~ 千亿行 预聚合计算 定时 / 实时 / 触发 预聚合结果 万级 ~ 百万行 用户查询 SUM / COUNT / AVG 查询路由 命中预聚合? 直接返回 毫秒级响应 回源查询 扫描原始数据 💡 核心思路: 用「预计算」换「查询速度」—— 把高频聚合提前算好,查询时直接命中,避免重复扫描原始数据。

这张图展示了预聚合的核心流程。左边是原始数据,中间是预聚合计算,右边是预聚合结果。用户查询进来后,先走路由判断能否命中预聚合。能命中就直接返回,毫秒级搞定;命中不了才回源扫描原始数据。

我的习惯:在设计预聚合模型时,我通常会先分析业务查询的「二八原则」——80% 的查询集中在 20% 的维度组合上。优先把这 20% 的维度组合做成预聚合,性价比最高。别一上来就想覆盖所有维度,那样预聚合本身会变得很臃肿,维护成本也高。

1.4 预聚合的代价

说了这么多好处,也得说说代价。预聚合不是免费的午餐:

  • 存储成本增加——预聚合结果需要额外的存储空间。我见过一个极端案例,预聚合表的大小是原始表的 3 倍
  • 数据延迟——预聚合是「算好了等查询」,所以数据有一定延迟。实时预聚合可以做到秒级,但做不到真正的实时
  • 维护复杂度——预聚合模型需要管理,比如增量更新、全量重建、过期清理等

避坑指南:我曾经接手过一个项目,前任工程师建了 200 多张预聚合表,覆盖了所有可能的维度组合。结果预聚合本身的维护成本比查询成本还高——每天跑预聚合任务要 6 小时,而且经常跑挂。后来我砍掉了 80% 的预聚合表,只保留最核心的 40 张,查询性能反而更稳定了。预聚合不是越多越好,够用就行。

好了,这一章的内容就到这里。预聚合的核心思想其实很简单——提前算好,随查随用。后面的章节我们会深入具体的实现技术,比如物化视图、OLAP Cube、实时聚合表等。到时候我会结合项目实战,一步步带你搭建一个完整的预聚合体系。