事务事实表非常适合记录特定事件,例如网站点击、产品销售或银行存款。然而,它们在回答有关系统状况的问题时效率不高。如果业务分析师问:“3月31日,产品X在所有仓库的总库存价值是多少?”,仅使用事务数据回答这个问题,需要汇总从开始到3月31日的所有入库和出库事件。随着历史数据量的增加,这种计算变得计算成本高且缓慢。定期快照事实表解决了这个性能瓶颈。这种表类型不是记录每个离散事件,而是以定期、可预测的间隔对实体的状态进行采样。它就像一台高速相机,在每天、每周或每月的结束时为您的业务流程拍照。结构和粒度定期快照的决定性特点是其粒度。事务粒度定义为“每事件一行”,而定期快照粒度定义为“每周期每实体一行”。设想一个每日库存快照。粒度由日期和产品(很可能还有仓库)的组合定义。即使产品当天没有销售或补货事件,仍然会生成一行来记录库存水平保持不变。这种结构差异造成了数据密度的根本区别:事务表是稀疏的: 只有当有活动发生时才存在行。定期快照是密集的: 无论是否有活动,每个时间段都存在行。由于快照是密集的,它们可以即时报告状态,无需复杂的重新计算。您只需查询所需的特定日期。digraph G { rankdir=LR; node [shape=box, style=filled, fontname="Arial", fontsize=10, margin=0.2]; edge [fontname="Arial", fontsize=9, color="#adb5bd"]; subgraph cluster_source { label = "来源:事务数据(稀疏)"; style = rounded; bgcolor = "#f8f9fa"; fontcolor = "#495057"; color = "#dee2e6"; t1 [label="行 1:1月1日 - 购买 10", fillcolor="#a5d8ff", color="#74c0fc"]; t2 [label="行 2:1月5日 - 销售 2", fillcolor="#a5d8ff", color="#74c0fc"]; t3 [label="...1月6-30日无活动...", shape=none, fillcolor="#f8f9fa", style=filled]; t4 [label="行 99:1月31日 - 销售 1", fillcolor="#a5d8ff", color="#74c0fc"]; } process [label="ETL 流程:\n计算日终状态", shape=ellipse, fillcolor="#e9ecef", color="#adb5bd"]; subgraph cluster_target { label = "目标:定期快照(密集)"; style = rounded; bgcolor = "#f8f9fa"; fontcolor = "#495057"; color = "#dee2e6"; s1 [label="1月1日:数量 10", fillcolor="#b2f2bb", color="#69db7c"]; s2 [label="1月2日:数量 10", fillcolor="#b2f2bb", color="#69db7c"]; s3 [label="...", shape=none, style=filled, fillcolor="#f8f9fa"]; s4 [label="1月31日:数量 7", fillcolor="#b2f2bb", color="#69db7c"]; } t1 -> process; t2 -> process; t4 -> process; process -> s1; process -> s2; process -> s4; }图表显示了从稀疏事务事件到密集定期快照的转换过程。注意,快照表即使在没有活动的日期也会生成行,以保持状态。半可加度量设计定期快照时,首要的技术考量是其中度量(数值事实)的行为。在事务表中,像 quantity_sold 或 sales_amount 这样的度量通常是完全可加的。您可以在所有维度上对它们求和。$$总销售额 = \sum_{所有维度} 销售金额$$在定期快照中,度量通常是半可加的。这意味着它们可以在某些维度上求和,但不能在所有维度上求和。求和失败最常见的维度是时间。以银行账户余额为例。跨客户(可加的): 您可以汇总1月1日所有客户的余额,以获得银行总负债。跨时间(不可加的): 您不能汇总1月1日和1月2日的余额。如果您星期一有100美元,星期二有100美元,您并没有200美元。在SQL中聚合半可加度量时,对于时间维度,您必须使用除 SUM() 之外的函数。常见的聚合包括 AVG()、MIN()、MAX() 或 LAST_VALUE()。例如,为了分析库存表现,您可能计算该月的平均每日库存:$$平均库存 = \frac{\sum_{d=1}^{n} 每日计数_d}{n}$$实施策略在数据仓库中实施这些表时,您通常会依赖于预定的ETL(抽取、转换、加载)作业,该作业在业务周期结束(例如午夜)后运行。确定粒度: 确定必要的频率。每日快照适用于快速流转的零售业,而每月快照可能足以满足财务分类账余额的需求。处理延迟数据: 定期快照假定提取时状态已定。如果1月31日的交易在2月2日才到达,您必须决定是否更新1月31日的快照行。在严格的会计系统中,快照可能保持静态,更正应用于当前期间。在分析系统中,您经常更新历史快照以反映实际情况。存储优化: 由于这些表是密集的,它们增长迅速。每天对100万个产品进行快照,每年会生成3.65亿行。按日期维度对该表进行分区对查询性能非常必要。事实表比较为了选择正确的模式,请比较业务用户需要回答的主要问题:特性事务事实定期快照事实主要问题“发生了什么?”“我们有多少?”数据密度稀疏(仅在事件发生时有行)密集(每个周期都有行)时间维度事件的具体时间戳期末日期度量类型大多可加(例如,销售数量)半可加(例如,余额,水平)数据量与活动成比例与(时间 × 维度)成比例通过在您的基础数据模型之上构建定期快照事实表,您可以为分析师提供高性能结构,用于趋势分析和状态报告,从而无需昂贵的即时计算。