数仓理论总结¶
组件和架构¶
架构¶
lambda架构¶
顾名思义,形似lambda,也就是离线和实时两条线并行。
整体分为批处理,流处理两个分支。其中流处理层负责快速计算,获得想要的结果,而批处理层负责大批量精确处理所有数据,并且最终可以将流处理层的非精确处理数据替换掉。
两者的计算结果最终都输出到服务层,服务层通过返回预先计算的数据视图,来相应app的查询。
kappa架构¶
也就是纯流式处理,去掉了批处理层,延迟更低。
但是与此同时带来两个问题
- 整个系统需要保持端到端的
exactly-once
。 - 系统处理历史数据的压力越来越大
流批一体¶
也就是将流数据和批数据放在同一个框架中,进行一体化处理。
- Spark
- 批处理:SparkSQL
- 流处理:StructStreaming
- Flink:可同时流批处理,通过改变计算图的触发时机来控制。
- Doris:也可以做流批一体,这个在官网和一本书上都看到过。
数仓建设¶
数据库类别¶
OLTP¶
即online-transcation-processing
,是面向当前数据的,以事务为核心的分析处理系统。最典型的就比如MySQL
等关系型数据库。通过前端触发后端相应,从而驱动数据库的状态改变。
OLAP¶
online-analysis-processing
,是面向当前数据,以及海量历史数据的,以主题为核心的分析处理系统。整个数据仓库系统就是一个OLAP。当然,我感觉一般说OLAP的话特指的是Doris
这类的OLAP引擎。
分层¶
原因¶
- 减少重复开发。可以将常用的表沉淀下来,减少不必要的开发,从而减少资源消耗。
- 数据血缘追踪。追踪每个表的上下游情况,表
owner
是谁,方便运维管理。 - 解耦。而不是烟囱式开发-直接从
ods
穿透。方便整体数据的修改和整理。 - 视角不同。不同的人关注不同粒度的数据,所以必然需要分层,这是必要性。不可能给每个职位的人同样一个粒度的数据报告。
内容¶
主要分为三大层,也就是ODS,CDM,ADS
。
- ODS 也称为操作数据层、数据贴源层。需要将不同数据源的数据同步到一起,进行简单的统一整理即可(比如两个数据源的同一个含义的字段使用不同类型进行存储)。
- CDM 公共维度模型层。用于存放明细事实数据,维度表数据,以及公共指标汇总数据。其中明细数据表,维度表通过ODS层数据加工而来,公共指标汇总数据通过明细数据表,维度表加工而来。
- DWD层:明细数据层,同时可以采用维度退化手段(空间换时间),提高明细数据表的易用性。
- DWS层:加强指标的维度退化,采用更多的宽表化手段来构建,提高公共指标的复用性,减少重复加工。一般是按照
周期、维度
来聚合成指标较多的宽表。需要在本层完成指标口径统一(比如xxx_1d,xxx_7d,xxx_td)表。 - ADS
- 按照
应用域
划分,存放数据产品的特化统计指标,其通过CDM层数据以及ODS层数据加工而来。 - 当然,如果多个应用使用同一个特化指标,可以将其沉淀到CDM层方便复用。
建模方法论¶
ER模型¶
也就是实体-关系模型。具体的话可以从1NF开始到3NF。
- 每个属性都不可再分
- 非主字段完全依赖于主键(复合主键的整体),不能单独依赖于其中的一部分
- 非主字段不能依赖于其他非主字段
这里一般说的是OLTP
中的ER模型,其是面向某个具体业务流程的实体对象关系的抽象。而其实OLAP
中也有ER模型,但是好像都不用这个。
维度模型¶
kimball
提出,通常有两种实现-星型模型和雪花模型。
- 星型模型
- 对数据做了冗余
- 效率较高
- 雪花模型
- 对数据拆到没有冗余
- 效率低下
建模流程如下
- 选择需要进行分析决策的业务过程。这个业务过程可以是单个业务事件,比如支付,退款。也可以是多个事件组成的业务流程,或者某个事件的状态。
- 选择粒度。通常,选择多个维度组合起来上卷,组成自己想要的粒度。
- 识别维表。通过需要的粒度组织必须的维度信息。
- 选择事实(具体数字)列,来确定分析需要衡量的指标。
建模流程¶
名词术语¶
数据域
面向业务分析,将业务过程或者维度进行抽象的集合。
业务过程
指的是企业的业务活动时间,比如下单,支付,退款。是一个不可拆分的行为事件。
度量
也成为原子指标。是某一个业务事件行为的度量,比如下单了xxx元
,也即支付金额等。
维度
维度是度量(原子指标)的环境,其属于一个数据域。通常有地理维度,或者时间维度。
派生指标
通常指的是一个原子指标 + 多个修饰词 + 时间周期。比如最近一天的某用户的消费总额。
构建流程¶
- 需求调研。面向不同主题的数据需求,是驱动数据仓库建设的根本。通常通过和业务结合最近的数分来收集。
- 数据域划分。数据域是面向业务分析,将业务过程和维度进行抽象的集合。比如可以构建出
商品域,日志域,交易域
等。以交易域为例子,其中由包含加购,下单,支付,退款,收获
等业务过程。 - 构建总线矩阵。做两件事情,分别是明确每个数据域的业务过程集合,以及每个业务过程所关联的维度。所以这个矩阵的纵轴是数据域下的业务流程,横轴是所有数据域的全局一致性维度。
- 规范定义,明确每个指标的口径(具体计算逻辑)。
- 模型设计。
维度设计¶
维度是维度建模的核心
来源
来源于和业务方的交谈,通常出现在group by / order by
语句之后。
维表设计
首先,从ODS中抽取一个来源于后台数据库的核心维度表,也称为主维表。
如果是数仓中的商品维度,则可以直接取业务数据库的商品维度作为主维表。
然后,确定相关维表。也就是通过分析,得出该维度表可能和哪些表有关系,比如商品表可能和商家,用户等维度有关系,可以将它们直接通过外键JOIN过来。
通常这个过程,就是维度表的反规范化,也就是将主维表,相关维表有用信息合并起来成为一张表。
最后,将这个大维度表进行筛选和列裁剪,取自己关心的最小集即可。
下钻
通过某个维度,可以对事实表进行下钻统计。也就是从最高类目 -> 一级类目 -> 二级类目等,细化粒度。
维度变化
数据仓库是要做历史统计的。但是维度可能随着时间的流逝,发生变化。比如商品维度中,某个商品之前是A类目,但是现在被划分到了B类目中。那么如何在一个汇聚了所有历史数据的数仓中处理这个维度变化呢?
有三种方式:
- 重写维度值:也就是直接将维度表的对应位置修改为最新值即可,之后无论新旧事实数据,所有的关联维度取的都是最新维度。
- 插入新的维度行:新加一个维度行,并增加两个时间戳字段,让新旧历史数据的维度有效分开。
- 添加新的维度列:新加一个维度列,JOIN的时候可以根据条件判断要新的还是旧的,从而可以在不同维度上卷。
极限存储(拉链存储)
使用的就是第二种方式,也就是插入新的维度行的方式。
也就是商品维度变更的时候,并不直接原地更新,而是拆分为两段。比如:
- t1-t2,类型1
- t2-now,类型2
其实思路类似于流表理论中的思想
,记录变化而不是直接汇总得出结果。其实WAL
也是类似思想。
如何对用户无感知呢?
阿里是直接在语法树部分改的,也就是对语法树遍历的时候生成AST树的时候,内部算子的条件会做自动的修改,做到对用户透明。
事实表设计¶
整体流程
- 识别业务过程
- 选择事实表类型
- 声明粒度和维度
- 确定度量值
- 维度退化
类型
事实表分为三种类型,分别是事务型事实表,累积快照事实表,周期快照事实表。
事务事实表-DWD层
一般一行代表一种业务过程的事务。
- 单事务事实表,一个表对应一种业务过程的事务。比如下单/签收。
- 多事务事实表(其实和下面的累积快照事实表类似),一个表对应多个业务过程的事务组合,比如从下单到签收。
适用于长生命周期的实体,比如用户。
累积快照事实表-DWD层
一行代表一个实体所设计到的多个业务过程的组合(反应完整的生命周期)。最重要的是记录每个流程的时间。
比如子订单从下单-支付-发货-收获的完整过程的时间组合。
其适用于短周期的实体,比如交易订单等。
周期快照事实表-DWS层
也就是最长td表,3d表
等经过汇总的数据,通过定期汇总,来压缩为周期的,不同粒度的快照数据。
事实表也有拉链存储,具体和维度表的拉链存储一样。
其他¶
数据域和主题域¶
数据域是数仓从上游数据源拿到数据之后,对数据的抽象组织。
而主题域是从下游数据应用层接到需求之后,对数仓自己所提供的数据服务领域的划分。
简单说,一个是从下开始,一个是从上开始。