数据建模方法论

如何理解数据仓库

从事数据开发后,再回头来看一看数据仓库的定义:数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。那么如何理解这几个关键词:

  • 面向主题的:主题(topic),即分类,专题分析。这里引入了主题模型的思想,实际操作中将数据按照业务线、业务模块层层细分。比如先划分大的业务域,每个业务域再按照业务过程划分数据域(一级、二级、三级数据域)。
  • 集成的:数仓系统和生产系统通常是隔离的,把跨源的、分散的多个业务DB的数据同步到数仓系统,按照一系列模型打成宽表的过程就是集成。
  • 相对稳定的:每天/每小时分区内数据不频繁更新,即一个任务正常每天只会向一个分区写入一次(回刷数据的时候除外),可以看作这部分数据是一个相对稳定的快照。
  • 反映历史变化的:每个周期(天/小时)的快照形成了历史全量数据,即拉多个分区进行聚合(dws)等操作便可以看到历史趋势。

如何设计数据仓库

这个问题可以从几个方面来看:

数据技术:

  • 数据采集:常见的有流量埋点日志的采集、数据库的binlog采集等。
  • 数据同步:采集的数据同步至数仓系统,数据量小可直连数据库平抽,数量大可通过消息队列传输日志。考虑的主要问题是如何数据延迟、数据飘逸(0点数据落到错误的分区)、删除(删历史数据、删最后一条数据)、遗漏(更新,补数)。
  • 数据开发:离线数据开发采用hive、spark sql、odps等,实时数据开发采用flink;存储采用hdfs、hbase、adb、doris、holo等。这里主要是开发技术深度和广度的积累。
  • 数据服务:加工好的数据可通过结果表、数据接口、分析看板等形式对外提供。服务以产品化的形式提供,主要考虑的是接口参数的约定,更新频次,qps、命名约定等。
  • 数据挖掘:基于加工好的数据训练模型,主要用到一些常见的机器学习算法和统计学知识。

数据模型:

  • 关系模型:Inmon提出,用实体和关系(E-R)来描述业务,符合3范式。站在企业角度自上而下的进行抽象、整合和主题建模。但是不适用于业务快速迭代的互联网数仓系统,因为实施周期长。
  • 维度建模:Kimboll提出,和Inmon相反的是维度建模自底向上的,面向需求/分析的进行建模。烟囱式的开发,开发周期快。常见的星型模型、雪花模型、星座模型等,实际操作中都是宽表化处理+生命周期,如淘系的大宽表,冗余维度和事实,通常都是几百个字段/标签,这也是目前的主要建模方法论。
  • 领域建模:宽表后期的维护很痛苦,后期演化出了一种面向领域对象建模的方法论,即将稳定的子域业务逻辑进行沉淀,每一个子域都是dwd,再将所有的子域dwd合成数据中台dwd,最后再分流到各业务线,进行业务逻辑的开发。

 

数据管理:

  • 元数据:记录了数据从产生到消费的全过程,如表的创建、调度、产出时间;各个表直接的血缘关系,层级定义;表的字段类型、存储位置、owner、计算成本、存储成本、生产日志等等。基于元数据我们可以做更
  • 计算管理:数据计算参数优化,选择高级参数;HBO:基于历史运行参数自动优化参数;CBO:基于统计metric和代价模型来优化任务;规则校验:自动化规则拦截,计算逻辑优化如谓词下推等。
  • 存储和成本管理:数据压缩优化,选取高压缩比格式:orc、parquet;数据重分布(repartition),降低shuffle开销、热点问题,提高查询效率;生命周期管理,定期或周期性地删除数据,或将增量数据合并到全量,或极限存储,冷数据归档等。
  • 数据质量:从四个方面衡量:完整性、准确性、一致性、及时性。可通过监控平台来预警,完整性即每天条数波动监控,是否有记录缺失;准确性即异常(空值、零值、负值等)监控;一致性如主备任务是否一致,全链路是否一致等;及时性即调度、产出时间保障,天级、小时级、实时产出等。

数据应用:

数据的常见应用形式:以数据资产的形式沉淀;以数据产品的形式对外开发放;或提供数据解决方案;还有以数据服务的形式对外开发接口。

数据模型

以维度建模为基础,有横有纵地构建总线矩阵。如下图:

  • 横向按照主题划分
  • 纵向按照层级划分
    • ods、dwd、dws不跨域,在同一个域内可保证产出时间
    • dm、app可跨域名,产出时间依赖上游最晚的域

横向建模

按照主题把数据分类存放,按照业务域、数据域和业务过程去切分。不同域的数据产出时间有先后顺序,那么一般是在集市层去整合。

  • 数据域:将业务过程或维度进行抽象,形成业务过程或维度的集合,还可继续拆分子集。
  • 业务过程:业务中一个不可拆分的行为事件,一般是原子的动作。
  • 主题:决策分析所关心的一个方面,一个分类。

纵向建模

按照分层规范,纵向的分为ods -> dwd -> dws ->app 层和 ods-> dim层

  • ods: 和源系统保持一致
  • dwd: 以业务过程驱动,基于业务过程的特点,构建最细粒度的明细层事实,并宽表化处理,冗余常见维度。
    • dwd_业务域_数据域_业务过程_自定义_<刷新周期><存储策略>
    • 刷新周期:表的分区更新频率,如天d、小时h、月m
    • 存储策略:每个分区的数据范围,全量f、增量i,合起来就是df,表示按照天更新全量。
  • dws: 以分析主题驱动,基于需求,构建公共粒度的汇总事实表,并宽表化处理,冗余常见维度
    • dws_业务域_数据域_粒度_自定义_<刷新周期><存储策略>
  • dim:基于维度建模思想,构建一致性的维度
  • dm: 数据集市,面向需求活分析场景,可连接跨域的维度和属性

事实表设计

事实表定义

  • 事实:描述业务过程的度量,如可以sum/count的交易金额。
  • 事实表:通过度量来表达业务过程,事实表紧紧围绕业务过程来设计。事实表结构应包含:
  • 数值度量:
    • 可加性:可按照任意维度汇总,如支付金额
    • 半可加性:可按照部分维度汇总,如一个商品的库存按月汇总起来是没有意义的。
    • 不可加性:不能汇总,如将汇率加起来是没有意义的
  • 主键、外键:用于关联
  • 退化维度:在事实表中冗余常见的维度属性(字段/列)
  • 粒度:一行数据所表达的业务细节程度,它确定了事实表的每一行表示什么级别的数据。如子订单粒度是最细节的数据,而父订单粒度的事实表细节程度更粗略一些。
    • 根据业务具体的含义来确定粒度,如只表示订单事实,那就选取订单id
    • 根据维度组合来确定,即组合key。如订单+状态,表示一笔订单从下单状态到签收状态的流转过程。
  • 核心原则:一个事实表不要混用多个不同级别的粒度,最好选择原子的/最细的粒度,这样能保持最灵活的可加性。

事实表设计步骤

  1. 选择业务过程,并确定事实表类型,确定主表
  2. 声明粒度,确定主键,只选取一种粒度,不同的粒度建不同的表。
  3. 确定维度,选择跟业务过程相关的一些维度,如买家、卖家、类目。
  4. 确定事实/度量。不可加的事实度量要分解为可加的(保留子项),只选择业务过程相关的事实,且相关的事实尽可能全,便于可扩展。
  5. 冗余维度,选择维度中的一些属性列(买家name,age),减少下游的关联次数。

事实表类型

1.事务事实表

  • 单事务事实表,是原子事实表,只包含一个业务过程,如只有支付时间和金额,那么每天的分区里面只有当天的支付订单。
  • 多事务事实表,有多个业务过程,如同时有创建时间、支付时间、完成时间,那么多个时间描述了完整的交易过程,每天分区里没有的时间置空。还可通过二级分区进行业务归档:当天创建未支付、当天创建且支付完成。
  • 事务表要求:
    • 父子事实:按最细粒度分摊到子项
    • 事实完整性:包含业务过程中尽可能多的度量
    • 事实一致性:保持度量一致,如单位、时区的统一
    • 事实可加性:分解为可加的原子度量

2.周期快照事实表

  • 周期快照表每一行是汇总了一个周期的数据,如按照1天、1周、1月汇总的。按照常用维度来声明粒度,粒度是周期性。包含半可加的度量,可以从事务表汇总而产出。
    • 单维度周期快照,商品维度的汇总表
    • 多维度周期快照,商家+商品维度的汇总表
    • 事务与快照形成了对比:事务 -> 快照, dwd -> dws
    • 附加事实:保存周期结束时候的度量,还可附加上一周的度量,形成对比。
    • 冗余多个日期度量:如一个dws通常计算了1d、7d、30d、180d、1y的汇总指标。

3.累积快照事实表

  • 每一行包含多个业务过程,工作流节点生命周期较长,且各个节点的时间间隔不规律。如一行记录包含了一个订单的创建、支付、发货、揽收、转运、投递、签收等时间。这种场景事务表很难满足需求,如计算任意两个时间节点的时间间隔,支付到发货时长,发货到签收时长。
    • 包含多个业务过程的日期,能描述业务全链路过程。
    • 数据不断更新和回刷,某一行的订单每天都会更新部分时间,比如今天支付,明天发货,那么明天才会写入发货时间,这是需要回刷数据。
    • 工作流节点非线性,各个节点流转过程不一致,如有的订单是从下单到签收的顺序更新,有的订单则会中途退款、或退货重新发货。那么整个累计快照表要设计要能覆盖所有分支链路的逻辑链路。 如:a -> b -> c -> d -> f 能覆盖下面两个分支链路:

                        a -> b -> c -> f

                        a -> c -> d

  • 保存全量数据,保留历史至今的所有数据。
    • 按照第一个创建时间分区,当天的分区包含了当天创建的订单,后面每天需要回刷该分区来更新其余时间节点。可通过动态分区写入的方式来实现,但是每天写多个分区性能不太好。
    • 按照修改时间分区,当天的分区包含了当天创建和修改的订单。 当天的数据作为增量表可以合并到全量表,合并后保证主键唯一。如果全量表过大,可以按照30天、100天等间隔进行归档。 这样每天只会更新当天的分区,merge依赖全量表t-1分区,那么全量表的生命周期可设置为2天,以节省存储。这是最常用的分区模型。
    • 按照结束时间分区,当天的分区包含了当结束掉的订单,没结束的单独写入一个固定分区。那么强依赖完结标志,如果没有完结标志就需要人为约定。

维表设计

维表定义

维度:描述事实发生的环境,即实体对象,如买家是一个实体。

维度属性:维度/实体对象的一个列/属性,如买家的名称,年龄,信用等级。维度属性通常是查询的约束条件,分组和筛选的标签,如group by name,age,level

维表设计步骤

  1. 选择维度或者新建维度,保证维度的统一
  2. 确定主维度表,一般是从ods表选择,如商品表
  3. 确定相关的维度表,即确定关联关系,如商品类目表
  4. 确定维度属性,先从主维表选取一些列,再从相关维表中选取一些列,或加工出一些列。
  • 原则:

1.维度属性的id和name应该成对出现,保持一致

2.父子维度同时出现,便于追溯和下钻

3.沉淀通用的常见维度

4.数值型字段如果作为维度,通常用于查询的约束条件,分组和筛选的标签

维度变化

  • 缓慢变化维:
    • type1: 覆盖历史记录
    • type2: 不覆盖,添加新的行,还要增加代理键,如自增id + 开始时间 + 结束时间
    • type3: 添不加新的列,当前列和历史列,用于对比
  • 历史拉链表:用缓慢变化维的type2方法来存维度数据,使用的时候要根据开始时间和结束时间来筛选最新的维度。使用成本高
  • 快照维表:每天保留一份全量维度数据,每次取最新的分区即可。这种方法简单,它淘汰了拉链表。
  • 极限存储:底层采用拉链表+压缩存储,上层通过透明映射给下游使用。
  • 微型维度:将一部分不稳定的维度从主维表中移除到新的扩展表,如新增的标签可放在扩展表中,按需取用。

---the end--

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值