趋近智
定义粒度是维度模型设计中最重要的决定。在创建任何表或定义任何列之前,数据架构师必须回答一个基本问题:事实表中的单行代表什么?
粒度决定了可用于分析的详细程度。它规定了系统的维度性,并确定了物理存储需求。模式设计中的一个常见错误是在没有精确定义粒度的情况下进行,这会导致事实表包含不同详细程度的混合数据。这种模糊性会导致指标重复计算和查询逻辑混乱。
粒度是你的数据的原子单元。在零售交易的场景下,你面临两种常见粒度选择:
如果你选择订单头粒度,你的事实表会记录总交易金额,但无法查看具体购买了哪些商品。如果你选择订单行粒度,你就能保留按单个商品、商品类别和品牌切分数据的能力。
通常,分析系统应默认使用尽可能低的粒度,常被称为原子粒度。尽管这会增加行数,但原子粒度提供了最大的灵活性。聚合总是可以从原子数据汇总而来,但你无法向下查看从未存储过的细节。
思考业务流程与结果表结构之间的关系。
不同的粒度决定了不同的描述性属性和指标。粒度选项 B 允许按商品进行分析,而粒度选项 A 不允许。
尽管具体的业务定义有所不同,但大多数粒度都属于三个技术类别之一。了解这些有助于为你的模式选择合适的模式。
这是最精细的详细程度。当业务事件发生时,会精确地创建一个行。例如,网站点击、仓库移动或银行转账。
这种粒度代表了业务在特定、定期间隔的状态视图。与随机发生的交易不同,快照是确定性的。一个典型例子是每日库存余额或每月银行对账单。这里的一行不代表一个事件,而是代表一个时期结束时的状态。
这适用于有明确开始和结束的工作流,例如订单处理或保险索赔。这里的粒度是“每个工作流实例一行”。当流程进入不同阶段时(例如,订单已下达 -> 已发货 -> 已送达),此行会更新。
UPDATE 操作,与仅追加模式相比,这在某些列式数据库中可能代价较高。当一个事实表试图同时存储多种粒度的数据时,模式设计会失败。
考虑一个销售事实表。销售数据以订单行粒度到达。然而,业务也提供在月和门店级别定义的销售目标(预算)。
如果你试图将每月预算目标存储在该月的每个订单行上,就会引入“扇出”问题。当分析师对 Budget 列求和时,他们会得到一个严重虚高的数字,因为每月目标会为每个售出商品重复。
聚合公式会失效,因为指标的粒度与表的粒度不匹配:
错误总计=i=1∑n(交易i×月度预算)为了解决这个问题,不同粒度的数据必须存放在不同的事实表中。你会设计一个 fact_sales 表(订单行粒度)和一个 fact_goals 表(月/门店粒度)。然后,这些表会在 BI 层或通过跨维度查询进行集成,而不是以违反粒度的方式进行物理连接。
在构建模式之前,你必须正式声明粒度。此声明作为表的约定。它通常包括识别业务流程以及与维度表的主要复合链接。
例如,发货事实表的粒度声明可能如下所示:
如果粒度定义变为“每个发货清单(卡车)一行”,则 Product 维度不再有效,因为一辆卡车可以运载多个商品。这说明粒度如何规定事实表中允许的外键。
粒度选择与表大小存在直接线性关系。从每月快照变为每日快照,行数约增加 30 倍。从每日快照变为单个交易,行数可能增加数千或数百万倍,这取决于交易速度。
以下图表呈现了一年内典型零售场景中粒度选择与行数之间的关系。
更细的粒度会导致行数呈指数级增长。原子交易粒度(红色)提供最详细的数据,但需要最多的存储和计算资源。
在现代云数据仓库中,存储相对便宜,计算可扩展。因此,建议几乎总是以交易(原子)粒度作为基础进行存储。如果查询性能因数据量而下降,你可以在原子数据之上构建周期性快照表作为派生聚合,但不应很少从聚合开始并丢弃细节。这种做法确保了模式能够满足未来可能需要详细历史分析的需求。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造