精选·数仓与建模

三种事实表:事务事实表、周期快照、累积快照怎么选

91学AI·2026/7/13·8 阅读

考察点

三种事实表是维度建模的必考知识点,面试官想确认你能根据业务过程的形态选对表型,而不是只会建流水表。常见追问:库存、余额该用哪种;订单从下单到签收的多状态怎么建模;两种表型能不能混用。

参考答案

事务事实表:记录瞬间发生的原子事件

一行对应一个业务事件,事件发生才插一行,不发生就没有记录。下单、支付、点击都是典型。特点是只插不改(append-only),数据天然可加,维度最丰富。

工程实践上,事务事实表按天分区,事件时间字段要保留原始时间戳而不是只留分区日期,否则跨天统计、实时离线对数都会出问题。它的局限:表达不了「状态随时间停留」的场景——你想知道每天 24 点的库存是多少,从事务流水里推要累加全历史出入库,代价大还容易错。

周期快照事实表:定期给状态拍照片

按固定周期(通常是天)对某个状态量做快照,一行 = 一个实体在一个周期末的状态。账户余额快照、商品每日库存快照、店铺每日在架商品数都是。它有两个标志性特征:

  • 每行都带一个快照日期维度,不管这天有没有变化都会有一行,所以数据量可预测、随时间线性增长;
  • 事实是半可加的:库存可以跨商品、跨仓库求和,但跨日期求和没有意义。这是面试加分点,说明你真踩过坑——新人最容易对着余额快照直接 sum 出「全月余额」这种荒谬指标。

周期快照回答的是「到某天为止是什么状态」这类问题,查询时 where dt = 某日期 直接取,不用累加历史,这是它相对从事务表推算的核心价值。代价是存储:一亿用户每天一行,一年 365 亿行,所以冷数据通常降采样(保留月末)或缩短生命周期。

累积快照事实表:跟踪一个流程的多个里程碑

面向有明确起点和终点、生命周期较长的业务过程,最典型的是订单履约:一行 = 一个订单,表里有下单时间、支付时间、发货时间、签收时间、完成时间多个日期外键,以及各阶段金额、各阶段耗时等事实。

它和前两种的本质区别是行会被反复更新:订单走到哪个里程碑,就更新对应的时间字段和状态。在 Hive 这种不擅长更新的引擎上,落地做法是每天把当天有变化的订单全量重刷一次(insert overwrite 整分区或按订单粒度 merge),用 Hudi/Iceberg 则可以走 upsert。

累积快照的价值在于分析流程效率:支付转化率、平均发货时长、各环节耗时分布,这些是事务表要自关联很多次才能算出来的。设计时要注意里程碑字段允许为空(流程没走到),耗时事实可以预计算好(支付时间 - 下单时间),下游就不用每次现算。

怎么选

判断路径很直接:业务过程是瞬间动作,用事务事实表;是状态量、关心「某时点是多少」,用周期快照;是有多阶段生命周期的流程、关心「走了多久、走到哪」,用累积快照。真实数仓里三者经常并存:下单用事务表,库存用周期快照,订单履约用累积快照,共享同一套维度。

对比项事务事实表周期快照累积快照
一行代表一次原子事件实体在某周期末的状态一个流程实例
更新方式只插入只插入(按周期批量)反复更新
日期维度1 个(发生时间)1 个(快照日期)多个(各里程碑)
可加性完全可加半可加(跨周期不可加)视事实而定
典型场景下单、支付、点击余额、库存订单履约、审批流

可能的追问

  • Hive 不支持高效更新,累积快照怎么落? 经典做法是 T+1 全量重算:从业务库重新拉订单当前状态,或者基于历史分区 + 当日增量 merge 出新分区,用分区覆盖代替行级更新。
  • 实时场景下这三种表还成立吗? 概念成立,实现变了:事务事实对应 Kafka 明细流,周期快照可以用 Flink 定时窗口或 OLAP 引擎的聚合物化,累积快照在 Flink 里用状态算子维护每个订单的里程碑进度。
  • 为什么周期快照不直接从事务表实时推算? 大促口径对不上时快照是权威数据源;而且推算依赖全历史流水,任何一条流水缺失都会污染后续所有时点,快照每周期独立生成,错误不累积。

评论 (0)

暂无评论,快来抢沙发吧!

91学AI

© 2026 91学AI · 按岗位学 AI 与大数据. All rights reserved.