2. 核心概念与术语:度量、维度、粒度、聚合表、物化视图

好,咱们正式开始聊预聚合模型之前,得先把几个基础概念掰扯清楚。这些术语你天天见,但真到了设计层面,理解深浅直接影响最终效果。我见过不少团队,就是因为对「粒度」的理解有偏差,导致聚合表建了一堆,查询却一点没快起来。

咱们一个一个来。

2.1 度量(Measure)——你要算的那个数

度量,说白了就是业务上关心的「数值」。销售额、订单量、点击次数、库存水位……这些都是度量。它们通常是可加、可聚合的数值字段。

在预聚合模型里,度量是聚合操作的目标。你建聚合表,本质上就是在不同维度组合下,提前把度量算好存起来。

度量的三种常见聚合方式:

  • 可加性度量:跨所有维度都能直接求和。比如销售额、订单金额。
  • 半可加性度量:只能沿部分维度求和。比如账户余额,按时间维度求和没意义,但按账户维度可以。
  • 不可加性度量:不能直接求和。比如比率、平均值、去重计数。

我在项目中遇到过最坑的情况,就是有人把「去重用户数」当普通度量直接 SUM,结果聚合表数据翻了好几倍。嗯,这里要注意:不可加性度量需要特殊处理,比如用 HyperLogLog 近似去重,或者保留明细再二次聚合。

2.2 维度(Dimension)——你从哪个角度切

维度就是你看数据的「角度」。时间、地区、产品类别、用户等级……这些都是维度。它们通常是离散的、枚举值有限的字段。

你想想看,一个查询慢,往往是因为它在维度组合上做了大量扫描。预聚合的核心思路,就是提前把常用维度组合下的度量算好,查询时直接读结果。

维度类型 示例 特点
时间维度 年、月、日、小时 层级分明,最常用
属性维度 城市、品类、渠道 基数可控,适合预聚合
高基数维度 用户ID、设备ID 基数大,预聚合收益低

我个人习惯,在设计维度时先问三个问题:

  1. 这个维度在查询中出现的频率有多高?
  2. 它的基数(唯一值数量)有多大?
  3. 它和其他维度有没有层级关系?

回答完这三个问题,哪些维度该进聚合表,基本就清楚了。

2.3 粒度(Granularity)——你的数据有多细

粒度,是预聚合模型里最容易被忽视的概念。它描述的是「一行数据代表什么」。比如:

  • 「每笔订单」是一条记录——这是明细粒度。
  • 「每个城市每天」是一条记录——这是聚合粒度。

粒度决定了聚合表的行数和查询能力。粒度越细,数据越灵活,但行数爆炸;粒度越粗,查询越快,但丢失细节。

我曾经踩过的坑: 给一个电商平台设计聚合表时,把粒度定在「商品+小时」级别。结果商品有 500 万 SKU,一天就产生 1.2 亿行聚合数据,存储和更新成本远超收益。后来改成「品类+天」粒度,行数降到 2 万,查询性能反而更稳定。

所以我的建议是:粒度选择要匹配查询模式。先看业务最常用的查询维度组合,再决定聚合粒度。别贪心,别想着一个聚合表覆盖所有场景。

2.4 聚合表(Aggregate Table)——提前算好的结果集

聚合表,就是按照指定的维度和粒度,提前把度量计算好并存储起来的表。它和原始明细表是「预计算」和「实时计算」的关系。

举个例子:

-- 原始明细表:orders
order_id, user_id, city, product_id, amount, order_time

-- 聚合表:daily_city_sales
sale_date, city, total_amount, order_count

查询「某城市某天总销售额」时,直接从聚合表读,不用扫描几亿条明细。这就是预聚合的核心价值。

聚合表的设计原则,我总结了几条:

  • 按查询频率排序:最常用的维度组合优先建表。
  • 控制维度数量:一般不超过 4-5 个维度,否则行数膨胀。
  • 区分更新策略:全量重建还是增量更新,取决于数据量。
  • 考虑存储成本:聚合表不是越多越好,要算 ROI。

2.5 物化视图(Materialized View)——数据库帮你维护的聚合表

物化视图,本质上就是聚合表的一种自动化实现。你定义好查询逻辑,数据库自动维护一份预计算结果。查询时,优化器自动路由到物化视图,对应用透明。

和手动聚合表相比,物化视图有几个优势:

  • 自动维护:基表数据变化时,物化视图自动刷新。
  • 查询透明:SQL 不用改,优化器自动匹配。
  • 一致性保证:不会出现明细和聚合数据不一致的情况。

但也不是没有代价:

  • 刷新延迟:实时性要求高的场景可能不适用。
  • 存储开销:每个物化视图都是一份独立存储。
  • 维护复杂度:物化视图多了,数据库的刷新调度会变复杂。

我的选择标准:

  • 数据量在千万级以下,查询模式稳定 → 手动聚合表,灵活可控。
  • 数据量在亿级以上,查询模式多变 → 物化视图,自动匹配省心。
  • 实时性要求高(秒级) → 放弃预聚合,用列存 + 索引硬查。

2.6 概念关系图

这几个概念不是孤立的,它们之间的关系可以用一张图说清楚:

预聚合核心概念关系图 原始明细数据 度量(Measure)+ 维度(Dimension) 粒度(Granularity) 聚合表(Aggregate Table) 手动聚合表 物化视图 粒度决定聚合表的行数,维度和度量决定聚合表的内容 手动聚合 vs 物化视图:前者灵活可控,后者自动透明

从图里可以看得很清楚:原始数据经过「度量+维度」的提取,再确定「粒度」,最终形成「聚合表」。而聚合表的实现方式有两种——手动建表或使用物化视图。整个链条的核心,就是用空间换时间。

2.7 小结

这五个概念,是预聚合模型的基石。我建议你花点时间,拿自己手头的业务数据,试着画一张类似的关系图。把度量、维度、粒度标清楚,再决定哪些组合值得建聚合表。