维度建模理论与数仓分层思想

维度建模理论与数仓分层思想

维度建模

ODS 层因为保留原始数据, 所以和业务数据库 (关系模型) 一样是关系模型.

DWD 层即进行了维度建模, 将下面的模型 ↓

维度建模理论与数仓分层思想_第1张图片

转化为了下面的维度模型, 即以事实表为中心, 周围有一圈的维度表 ↓

维度建模理论与数仓分层思想_第2张图片

维度模型中的表数据 (数据特征) 可能有冗余, 但查询时一般只需要进行事实表和维度表进行 join, 不用 join 太多表, 查询性能更好.

在维度建模的基础上又分为三种模型:星型模型、雪花模型、星座模型。

但生产中事实表不可能只有一张, 所以多个事实表多个维度表结合形成了星座模型:

维度模型的好处

  • Understandability: 表结构简单, 分析人员更好理解事实与维度数据的表结构;
  • Performance: 减少 join, 提高查询性能;
  • 方便进行 OLAP 多维分析: 后续数仓中单纯的聚合值意义不大, 一般需要计算某些维度下的聚合值才有意义, 比如 select 维度 agg(事实) from table group by 维度.

维度模型的扩展

维度模型对数据关系的变化也具有很高的适应性. 当发生以下变化时, 不需要改变现存的 BI 查询或应用, 就可以方便地适应, 且查询结果不会有任何改变:

  • 新增的事实与存在的事实表粒度一致时, 可以创建新列;
  • 如果新增的维度表与事实表的粒度一致, 可以通过在事实表中建立新的外键列, 可以将新的维度关联到已经存在的事实表上.
  • 如果某维度表新增的维度列, 直接在维度表上建立新列即可;
  • 可以使事实表的粒度更原子化, 方法是在维度表上增加属性, 然后以更细的粒度重置事实表, 小心保存事实表及维度表的别名.

星型模型与 OLAP

如果, DW 采用了星型模式建模, 或 OLAP 建模, 都可以说是利用了维度的概念, 他们对维度的认识是一样的, 只是物理实现上不一样. OLAP 一般用于即席查询, 通常会进行与计算, 索引策略和其他的优化方法; 同时有很多比 SQL 更好的分析函数, 使得OLAP的查询和分析性能更好, 不需要提出新的查询.

但是, 一般在 OLAP 之前, 我们还是会将详细的, 原子的信息加载到星型模型中, 然后由此建立 OLAP 分析模型.

星型模型主要包含事实表, 以及通过主键/外键关系与之关联的维度表, 联机分析处理 ( OLAP) 多维数据库是实现在多维数据库之上的多维结构, 它与星型模型内容等价, 或者说来源于星型模型.

OLAP 多维数据库也是包含维度属性和事实表, 但它能够使用比 SQL 语言具有更强的分析能力的语言访问, 比如 XMLA 和 MDX 等.

OLAP 多维数据库通常是部署 DW/BI 的最后步骤, 或者作为基于多个原子关系型模式的聚集结构.

事实表

事实表

事实表中的每行数据代表一个业务事件或业务度量, 比如下单, 支付, 退款, 评价等.

事实表一般包含两部分字段:

  • 维度字段. 即与维表相连接的外键, 通常具有两个和两个以上的外键, 外键之间表示维表之间多对多的关系.
  • 度量值. 即具有可加性的数值型的度量值, 像可统计次数, 个数, 金额等. 例如, 订单事件中的下单金额.

事实表的特征:

  • 非常的大;
  • 内容相对的窄: 列数较少;
  • 经常发生变化, 每天会新增加很多.

维度建模理论与数仓分层思想_第3张图片

事实度量

最终计算通常在 DW 的上层或 OLAP 多维数据库层.

可加

最主要是数值类型和可加类型:

  • 数值类型: 销售额
  • 可加类型: 销售量

这些都可以按照某些维度, 比如时间维度进行聚合, 这是最关键的.

半可加

半可加度量可以对某些维度进行汇总, 但不能对所有维度进行汇总.

比如, 差额是常见的半可加事实, 除了时间维度外, 他们可以跨所有维度进行加法操作.

不可加

比率是最常见的不可加度量.

一般对于这种, 非可加度量一般拆解为其全完可加分量.

粒度 - 事实表分类

事实表中每行数据是一个特定级别的细节数据, 称为粒度. 同一张事实表的粒度相同, 不会出现重复计算度量的问题.

事务型粒度 (最常见)

最常见, 最典型的事实表. 它和上面介绍的事实表的基本描述是一样的.

每个事务或事件为单位,例如一个销售订单记录,一笔支付记录等,作为事实表里的一行数据。一旦事务被提交,事实表数据被插入,数据就不再进行更改,其更新方式为增量更新。

特点:

  • 数据写入这样的事实表中就不会再进行修改了.
  • 最多.
  • 数据维护: 不变.
  • 采集中的同步策略: 增量 (数据不会变, 每天增量分区表).

无事实事实表

有些可能没有可以记录的数字化事实, 比如:

  • 某一天学生参加课程的时间, 包含时间, 学生, 教师, 地点, 课程等维度, 但没有数字度量.
  • 客户交际也是一种事件, 也没有相关的维度.

比如日志数据, 一般也可以转换成无事实事实表.

周期型快照粒度

周期型快照事实表中不会保留所有数据 (这句话是跟事务型事实表进行对比的),只保留固定时间间隔的数据,例如每天或者每月的销售额,或每月的账户余额, 或者加购物车事实表。

比如加购物车事实表:

最原子性的事件是加购物车和取消购物车, 但我们并不关注加减的过程或加了几次, 减了几次, 我们关注的是购物车中剩下的商品, 这些商品可能就是用户想买却舍不得买的商品, 这样我们就可以对其进行一个促销, 让大量用户进行购买, 这是我们关注的.

而购物车中的商品每天都可能会有变化, 所以我们一般周期性地记录购物车中的数据.

数仓中的具体实践是在 Hive 中建立日期为分区的购物车事实表, 然后 MySql 中的购物车表每天固定时间导入到 Hive 的当天日期分区中, 也就是每天打一个快照.

特点:

  • 相对较少.
  • 数据维护: 不变.
  • 采集中的同步策略: 全量 (每天全量分区表).

累积型快照粒度

累计快照事实表用于跟踪业务事实的变化。例如,数据仓库中可能需要累积或者存储订单从下订单开始,到订单商品被打包、运输、和签收的各个业务阶段的时间点数据, 来跟踪订单生命周期进展情况

当这个业务过程进行时,事实表的记录也要不断更新。也就是一行数据没办法一次写完, 需要分多个阶段累计写完的, 每个阶段都是一个里程碑.

订单id 用户id 下单时间 打包时间 发货时间 签收时间 订单金额
3-8 3-8 3-9 3-10

特点:

  • 最少.
  • 数据维护: 不像事务型事实表和周期型快照事实表, 累积型快照事实表每行数据是会改变的. 但 Hive 一般不对数据进行修改, 而是采用先 select 查询出来, 查询过程中进行判断, 看需不需要修改数据, 需要改的话进行修改, 修改之后, insert overwrite 回原表.
  • 采集中的同步策略: 新增及变化 (一般按照第一个里程碑时间建立分区表).

维度表

维度表: 一般是对事实的描述信息. 每一张维表对应现实世界中的一个对象或者概念. 例如: 用户, 商品, 日期, 地区等.

数仓的好坏取决于维度的设置, 分析能力取决于维度的质量和深度.

属性应该包含真实使用的词汇, 而不是令人感到迷惑的缩写, 尽量少使用代码, 而是使用文本.

操作码

有的操作码有确定的业务含义, 比如前两位表示业务类别, 3~4位表示区域, 与其用户查询过滤操作码, 不如前期就将操作码差分, 然后以不同维度展现给用户, 这样用户就能方便地展开过滤, 分组和制作报表等工作. 其实就是一个 ETL 的过程.

在分析操作码时, 如何确定某些元素是维度还是事实?

  • 包含多个值并后续参与计算, 往往是事实属性;
  • 对具体指的描述, 是一个常量, 某一约束和行标识, 往往是维度属性.
  • 连续值是事实, 离散型的不太大的列表一般是维度. 价格由于经常变化, 可以认为是一种事实度量.

维表的特征

  • 维表的范围很宽 (具有多个属性, 列比较多, 一般都是宽表 50 ~ 100 个), 比如将日期或者商品相关的字段全部放入一个表里;
  • 通常以层次关系表示.
  • 跟事实表相比, 行数相对较小: 通常 < 10万条;
  • 内容相对固定 (跟事实表对比): 像事实表, 比如订单表, 每下单一次就增加一行, 每天增加很多. 但维度表比如商品表, 即每天的商品表, 改变并不大, 因为每天商品基本一样, 不可能说每天上架大量的商品. 还有些编码表, 地区表和时间表等都不会变.
  • 同步策略: 除了某些特殊不变的维度表只在第一次初始化的时候全量同步一次, 其他的维度表一般来说每日全量同步. 注意: 像用户维度表使用的是拉链表, 这个需要注意一下, 还有拉链表是否需要分区等等, 待探讨.

维度表举例 - 时间维度表

日期ID day of week day of year 季度 节假日
2020-01-01 2 1 1 元旦
2020-01-02 3 2 1
2020-01-03 4 3 1
2020-01-04 5 4 1
2020-01-05 6 5 1

数据仓库各层建模

ODS

  • 保持数据原貌不做任何修改,起到备份数据的作用.
  • 数据采用压缩 lzo (数据是 load 来的),减少磁盘存储空间(例如:原始数据100G,可以压缩到10G左右. 如果采用列式存储 (同样类型数据压缩到一起), 压缩效率会更高).
  • 创建分区表,防止后续的全表扫描.

DWD

ETL + 维度建模.

ETL

日志数据在 DWD 层按照内容解析, 分为 5 类, 解析成 5 张表: 页面, 曝光, 事件操作, 启动, 错误.

这里用到自定义解析 json 的函数.

维度建模

DWD层需构建维度模型,一般采用星型模型,呈现的状态一般为星座模型。

维度建模一般按照以下四个步骤

选择业务过程→声明粒度→确认维度→确认事实

1 选择业务过程

在业务系统中,挑选我们感兴趣的业务线,比如下单业务,支付业务,退款业务,物流业务,一条业务线对应一张事实表。

尽可能全地选择业务, 以应对后续业务需求的变更.

2 声明粒度

数据粒度指数据仓库的数据表中保存数据的细化程度或综合程度的级别

一张事实表需要确定一个表的粒度, 即声明粒度意味着精确定义事实表中的一行数据表示什么,应该尽可能选择最细粒度,以此来应各种各样的需求。

为什么选择最细粒度? 我们从 DWD 层进行聚合时是从最小粒度开始聚合的, 最小粒度可以聚合为更粗的粒度, 但反之只有粗粒度是无法得到细粒度的. 所以有了最小粒度就意味着可以聚合得到各种粒度.

典型的粒度声明如下:

  • Order Detail 中,每行数据对应一个订单中的一个 sku,Order Info 中,每行数据对应一个订单, 所以订单事实表最细粒度为一个订单中的一个 sku. 但我们实建模过程中并不是完全遵照这样的, 就比如对下单来说应该是按照 Order Detail 中的 sku 来声明最细粒度, 但是对于下单, 我们其实建立了两个事实表, 一个 Order Info 事实表按照一个订单来声明粒度, 一个 Order Detail 事实表按照一个订单中的一个 sku 声明粒度. 这样做的好处? 因为有些需求我们是没必要去最细粒度去查询聚合的, 通过粗粒度事实表反而更容易获取, 比如, 想统计今天订单金额的总和, 按照 Order Detail 粒度就是每个商品价格和数量相乘再相加, 这样 数据量和计算量大, 反而不如在 Order Info 中直接对每一个订单金额求和即可来得方便.
  • 比如支付事实表, 我们只有一张 Payment Info 表, 那么支付事实表的最细粒度就是这张表的每一行数据指代的内容: 一条支付记录.
  • 一般情况下, 如果一个业务事实只有一张表的话, 粒度也就被确认了, 没有其他选择.
3 确定维度

维度的主要作用是描述业务事实,主要表示的是 “谁,何处,何时” 等信息。

实际上就是确定事实表中有哪些外键.

一般就是先把所有维度列出来, 然后看每个事实表和哪些维度 (group by 的字段) 有关.

4 确定事实

此处的 “事实” 一词,指的是业务中的度量值,例如

订单金额、下单次数, 单价, 折扣, 净支付价格等。

在 DWD 层,以 业务过程为建模驱动,基于每个具体业务过程的特点,构建最细粒度的明细层事实表。事实表可做适当的宽表化处理。

粒度 时间 用户 地区 商品 优惠券 活动 编码 快递商 仓库 度量值
订单 一条订单 件数/金额
订单详情 订单中一件商品 件数/金额
支付 一条支付记录 金额
加购物车 一个购物车记录 件数/金额
收藏 用户一次收藏 个数
评价 一次评价 个数
退款 一次款款记录 件数/金额
优惠券领用 一个用户领一个券的记录 个数

这些关系是比较灵活的, 但前提是能关联上的, 能关联上的尽量关联上.

什么是能关联上? 一般关系模型的一张事实表中的维度外键是直接关联上的, 但还有一些是可以间接关联上的. 比如支付表和位置, 直接关联不上, 但支付和订单相关, 订单和位置相关, 这样就关联起来了.

至此,数仓的维度建模已经完毕,DWS、DWT 和 ADS 和维度建模已经没有关系了。

DWS 和 DWT 都是建宽表,宽表都是按照主题去建。主题相当于观察问题的角度。对应着维度表。

DWS & DWT

这两层是款表层.

DWS

统计各个主题对象的当天行为,服务于 DWT 层的主题宽表。

维度建模理论与数仓分层思想_第4张图片

DWT

以分析的主题对象为建模驱动,基于上层的应用和产品的指标需求,构建主题对象的全量宽表。

维度建模理论与数仓分层思想_第5张图片

DWS 和 DWT 的作用

DWS 和 DWT 都一定程度进行了聚合, 没有 DWS 和 DWT 层可以吗? 可以, 但是:

  • 有些聚合操作是重复的, 需要重复计算;
  • DWD 是明细数据, 都从这一层去查询, 数据量比较大.

所以 DWS 和 DWT 层存在的意义就是减少数据重复计算, 提高数据的复用性, 优化数仓性能.

举例, 有以下需求:

1 统计今天每个省份订单的个数是多少?

select province, count(*) from orderInfo group by province where dt = 'xxxx-xx-xx'

2 统计今天每个省份下单的总金额是多少?

select province, sum(amount) from orderInfo group by procince where dt = 'xxxx-xx-xx'

这两个需求其实是类似的, 但如果从 DWD 来查询, 重复计算了两遍, 降低了效率.

DWS 和 DWT 设计

从上面来看, 对于相同维度的聚合, 我们可以进行一次计算, 所以, DWS 和 DWT 层宽表应该以:

  • 维度为基准 (宽表有哪些);
  • 所有与此维度相关的事实表中的度量值的聚合值为字段 (宽表有哪些字段).
  • 时间尺度不同:
    • DWS 为每个维度对象的当天的统计值;
    • DWT 为每个维度对象的累积值 (订单金额, 次数等…), 比如最近 7 天, 最近 15 天, 最近一个月, 从开始至今的累积值等.

DWD 和宽表层的关系

DWD 层进行了维度建模, 款表层只是我们为了优化数仓建的两层, 和维度建模没有任何的关系.

DWD 进行维度建模时不是以需求为驱动的, 主要以维度建模思路和步骤驱动的; 款表层是由需求指标为驱动的.

ADS

对电商系统各大主题指标分别进行分析。

对接数据仓库后续的应用, 比如 BI 报表, 用户画像, 机器学习等. 这些应用都需要数仓中的数据, 它们需要什么数据, 我们就在 ADS 层提供对应的数据.

比如, BI 报表需要展示结果, 比如一个聚合值, 那我们就把这个聚合值放到 ADS 层以供 BI 查询即可, 比如日活, 月活, 留存用户, 新增用户等.

比如, 机器学习需要大量的样例数据, 也可以放入 ADS 层;

比用户画像需要用户大量的各种信息, 也可以放在 ADS 层.

也就是说, 不同的应用, 在 ADS 层准备的数据是不同的.

维度建模举例

零售

选择业务过程

建模的业务过程是 POS 零售交易, 该数据保证商业用户能够分析被销售的产品, 他们是在哪几天, 在哪个商店, 处于何种促销环境中被销售的.

声明粒度

最细粒度是 POS 交易的每个单品, 假设 POS 系统按照一个购物车中某种产品.

确定维度

日期, 产品, 门店, 促销, 收银员, 支付方式

确定事实

销售数量, 单价, 折扣, 净支付价格;

扩展折扣额;

扩展销售额 = 销量 ✖️ 单价;

扩展成本;

扩展毛利润;

维度建模理论与数仓分层思想_第6张图片

维度表

日期维度表

维度建模理论与数仓分层思想_第7张图片

维度建模理论与数仓分层思想_第8张图片

产品维度

维度建模理论与数仓分层思想_第9张图片

维度建模理论与数仓分层思想_第10张图片

维度建模理论与数仓分层思想_第11张图片

引用

确定事实

销售数量, 单价, 折扣, 净支付价格;

扩展折扣额;

扩展销售额 = 销量 ✖️ 单价;

扩展成本;

扩展毛利润;

[外链图片转存中…(img-PXM3uxaq-1606195310738)]

维度表

日期维度表

[外链图片转存中…(img-199gR92j-1606195310738)]

[外链图片转存中…(img-p8VNuXAQ-1606195310739)]

产品维度

[外链图片转存中…(img-fF1sRQXp-1606195310740)]

[外链图片转存中…(img-HZIF5K6e-1606195310740)]

[外链图片转存中…(img-wekvGH3U-1606195310741)]

引用

Kimball - 数据仓库工具箱

你可能感兴趣的:(数据分析,数据库,大数据)