|
| 1 | +# 维度建模理论之事实表 |
| 2 | + |
| 3 | +## 1 概述 |
| 4 | + |
| 5 | +事实表,作为数仓维度建模的核心,紧紧围绕业务过程来设计。其包含: |
| 6 | + |
| 7 | +- 与该业务过程有关的维度引用(维度表外键) |
| 8 | +- 该业务过程的度量(通常是可累加的数字类型字段) |
| 9 | + |
| 10 | +### 1.1 特点 |
| 11 | + |
| 12 | +事实表通常较“细长”,即列较少,但行较多,且行的增速快。说明尽量使用维度外键,而不要 join 过来。 |
| 13 | + |
| 14 | +事实表是用来记录业务事件(如销售交易、点击事件等),这些记录的属性大多是数值(代表度量指标),如金额、数量、时间等,它们与维度表中的描述性信息相关联。 |
| 15 | + |
| 16 | +标准星型模式中,事实表包含维度表的外键,这些外键指向各维度表的唯一关键字,该设计是为提高查询性能: |
| 17 | + |
| 18 | +1. **避免数据冗余**: |
| 19 | + - 通过仅在事实表中存储维度外键,而不是维度表中的详细描述性信息,可以减少数据冗余和表的大小。 |
| 20 | +2. **查询性能**: |
| 21 | + - 由于事实表一般很大并且查询频繁,保持它们“瘦而长”有助于减少在执行查询时要扫描的数据量,从而提高查询性能。 |
| 22 | +3. **灵活度**: |
| 23 | + - 对维度数据的任何更改(如修改维度属性)只需在维度表中进行一次,而不需要更新事实表中的数据。这提高了数据仓库的灵活性和维护性。 |
| 24 | +4. **简洁的查询**: |
| 25 | + - 通过使用外键与维度表连接,SQL查询通常更加简洁,易于编写和理解。 |
| 26 | + |
| 27 | +通常设计和查询数据仓库时,应尽量避免在事实表中直接包含来自维度表的详细信息。当需要详细的描述性信息时,可以在查询中通过JOIN操作,将事实表与相应的维度表结合起来,以获取所需的上下文信息。 |
| 28 | + |
| 29 | +如要查询特定时间段内按产品分类的销售总额: |
| 30 | + |
| 31 | +```sql |
| 32 | +SELECT |
| 33 | + p.category, |
| 34 | + SUM(f.sales_amount) # 事实表,包含了销售金额和产品ID(维度外键) |
| 35 | +FROM |
| 36 | + fact_sales f |
| 37 | +JOIN |
| 38 | + # dim_product 是维度表,存储了产品的详细分类信息 |
| 39 | + dim_product p ON f.product_id = p.product_id |
| 40 | +WHERE |
| 41 | + f.sale_date BETWEEN '2021-01-01' AND '2021-12-31' |
| 42 | +GROUP BY |
| 43 | + p.category; |
| 44 | +``` |
| 45 | + |
| 46 | +通过使用产品ID将这两个表连接起来,可轻松得到按类别划分的销售总额。 |
| 47 | + |
| 48 | +综上,事实表的设计应该侧重于度量性能和减少存储占用,并通过在查询时与维度表的关联来提供分析所需的详细上下文。这样的设计有利于数据仓库系统的扩展性和查询性能。 |
| 49 | + |
| 50 | +### 1.2 分类 |
| 51 | + |
| 52 | +事实表有三种类型: |
| 53 | + |
| 54 | +- 事务事实表 |
| 55 | +- 周期快照事实表 |
| 56 | +- 累积快照事实表 |
| 57 | + |
| 58 | +## 2 事务型事实表 |
| 59 | + |
| 60 | +### 2.1 概述 |
| 61 | + |
| 62 | +事务事实表用来记录各业务过程,它保存的是各业务过程的原子操作事件,即最细粒度的操作事件。粒度是指事实表中一行数据所表达的业务细节程度。 |
| 63 | + |
| 64 | +事务型事实表可用于分析与各业务过程相关的各项统计指标,由于其保存了最细粒度的记录,可以提供最大限度的灵活性,可以支持无法预期的各种细节层次的统计需求。 |
| 65 | + |
| 66 | +### 2.2 设计流程 |
| 67 | + |
| 68 | +一般遵循步骤: |
| 69 | + |
| 70 | +#### 2.2.1 选择业务过程 |
| 71 | + |
| 72 | +在业务系统中,挑选我们感兴趣的业务过程,业务过程可以概括为一个个不可拆分的行为事件,例如在线教育交易中的下单,付款,加购等,都是业务过程。通常情况下,一个业务过程对应一张事务型事实表。 |
| 73 | + |
| 74 | +#### 2.2.2 声明粒度 |
| 75 | + |
| 76 | +业务过程确定后,需要为每个业务过程声明粒度,即精确定义每张事务型事实表的每行数据表示啥,应尽可能选择最细粒度,以应对各种细节程度需求。 |
| 77 | + |
| 78 | +典型的粒度声明: |
| 79 | + |
| 80 | +订单事实表中的一行数据表示:一个订单中的一门课程。 |
| 81 | + |
| 82 | +#### 2.2.3 确定维度 |
| 83 | + |
| 84 | +确定维度具体是指,确定与每张事务型事实表相关的维度有哪些。 |
| 85 | + |
| 86 | +确定维度时应尽量多的选择与业务过程相关的环境信息。因为维度的丰富程度就决定了维度模型能够支持的指标丰富程度。 |
| 87 | + |
| 88 | +#### 2.2.4 确定事实 |
| 89 | + |
| 90 | +“事实”指每个业务过程的度量值(通常是可累加的数字类型的值,如次数、个数、件数、金额等)。 |
| 91 | + |
| 92 | +经过上述四个步骤,事务型事实表就基本设计完成了。第一步选择业务过程可以确定有哪些事务型事实表,第二步可以确定每张事务型事实表的每行数据是什么,第三步可以确定每张事务型事实表的维度外键,第四步可以确定每张事务型事实表的度量值字段。 |
| 93 | + |
| 94 | +### 2.3 不足 |
| 95 | + |
| 96 | +事务型事实表可以保存所有业务过程的最细粒度的操作事件,故理论上其可以支撑与各业务过程相关的各种统计粒度的需求。但对于某些特定类型的需求,其逻辑可能会比较复杂,或者效率会比较低下。如: |
| 97 | + |
| 98 | +#### 1 存量型指标 |
| 99 | + |
| 100 | +例如购物车存量,账户余额等。此处以在线教育中的加购业务为例,加购业务包含的业务过程主要包括加购物车和减购物车,两个业务过程各自对应一张事务型事实表,一张存储所有加购物车的原子操作事件,另一张存储所有减购物车的原子操作事件。 |
| 101 | + |
| 102 | +假定现有一个需求,要求统计截至当日的各用户各科目的购物车存量。由于加购物车和减购物车操作均会影响到购物车存量,故需要对两张事务型事实表进行聚合,且需要区分两者对购物车存量的影响(加或减),另外需要对两张表的全表数据聚合才能得到统计结果。 |
| 103 | + |
| 104 | +可以看到,不论是从逻辑上还是效率上考虑,这都不是一个好的方案。 |
| 105 | + |
| 106 | +#### 2 多事务关联统计 |
| 107 | + |
| 108 | +例如,现需要统计最近30天,用户下单到支付的时间间隔的平均值。统计思路应该是找到下单事务事实表和支付事务事实表,过滤出最近30天的记录,然后按照订单id对两张事实表进行关联,之后用支付时间减去下单时间,然后再求平均值。 |
| 109 | + |
| 110 | +逻辑上虽然并不复杂,但是其效率较低,因为下单事务事实表和支付事务事实表均为大表,大表join大表的操作应尽量避免。 |
| 111 | + |
| 112 | +可以看到,在上述两种场景下事务型事实表的表现并不理想。下面要介绍的另外两种类型的事实表就是为了弥补事务型事实表的不足的。 |
| 113 | + |
| 114 | +## 3 周期型快照事实表 |
| 115 | + |
| 116 | +### 3.1 概述 |
| 117 | + |
| 118 | +周期快照事实表以具有规律性的、可预见的时间间隔来记录事实,主要用于分析一些存量型(例如购物车存量,账户余额)或者状态型(空气温度,行驶速度)指标。 |
| 119 | + |
| 120 | +对于购物车存量、账户余额这些存量型指标,业务系统中通常就会计算并保存最新结果,所以定期同步一份全量数据到数据仓库,构建周期型快照事实表,就能轻松应对此类统计需求,而无需再对事务型事实表中大量的历史记录进行聚合了。 |
| 121 | + |
| 122 | +对于空气温度、行驶速度这些状态型指标,由于它们的值往往是连续的,我们无法捕获其变动的原子事务操作,所以无法使用事务型事实表统计此类需求。而只能定期对其进行采样,构建周期型快照事实表。 |
| 123 | + |
| 124 | +## 4 累积型快照事实表 |
| 125 | + |
| 126 | +### 4.1 概述 |
| 127 | + |
| 128 | +累积型快照事实表是基于一个业务流程中的多个关键业务过程联合处理而构建的事实表,如交易流程中的试听、下单、支付等业务过程。 |
| 129 | + |
| 130 | +累积型快照事实表通常具有多个日期字段,每个日期对应业务流程中的一个关键业务过程(里程碑)。 |
| 131 | + |
| 132 | +| **课程id** | **用户id** | ***\*试听日期\**** | ***\*下单日期\**** | ***\*支付日期\**** | **订单分摊金额** | **支付分摊金额** | |
| 133 | +| ---------- | ---------- | ------------------ | ------------------ | ------------------ | ---------------- | ---------------- | |
| 134 | +| 1001 | 1234 | 2022-02-19 | 2022-02-20 | 2022-02-21 | 1000 | 1000 | |
| 135 | + |
| 136 | +累积型快照事实表主要用于分析业务过程(里程碑)之间的时间间隔等需求。例如前文提到的用户下单到支付的平均时间间隔,使用累积型快照事实表进行统计,就能避免两个事务事实表的关联操作,从而变得十分简单高效。 |
0 commit comments