本篇讨论退化维度。该技术减少维度的数量,简化维度数据仓库的模式。简单的模式比复杂的更容易理解,也有更好的查询性能。当一个维度没有数据仓库需要的任何数据时就可以退化此维度。需要把退化维度的相关数据迁移到事实表中,然后删除退化的维度。
退化维度官方定义:
就是那些看起来像是事实表的一个维度 关键字 ,但实际上并没有对应的维度表,其中,事实表的粒度就是文档本身或文档中的一个分列项。 具体怎么理解呢?在传统的父子 关系型数据库 中,事务编号是事物标题记录的关键字,比如订单编号、发票编号,这样的纪录包含了诸如事务日期、供应商标示这样在总体上对事务有效的所有信息。但在给出的维度模型中,已经将这些令人感兴趣的标题信息抽取出来放到其它 维度 中去了。但这个事务编号仍然十分有用,因为它可以作为组关键字而将单个事务中处理的明细集中在一起。
尽管这个事务维度看起来是一个维度关键字,但当把事务维度所有的描述性项目进行剔出后,形成维度为空。诸如这种事务编号、固有的操作型票据编号,应该自然的放入事实表中,而不用连接到维度表。退化维度在事实表粒度表示单个事务或事务分列项目时是很常见的,因为它标示父实体的惟一标示。订单号,发票号与提货单编号等几乎总是以退化维度的形式出现在维度模型之中。同时,退化维度在事实表主关键字方面也有一定作用。比如将订单事实表主关键字可以由退化的订单编号和产品组关键字组成。
举例解释:
假设我们有这样一张事实表(多事务):服务订购订单事实表
表结构如下:
order_id | 订单id |
buyer_id | 订购者ID |
severice_id | 服务ID(691175:商城版;690529:小程序;2085817039:旺铺卡) |
severice_name | 服务名称 |
order_type | 订单类型(0:新订购 ,1:续订 ,2:升级) |
crt_order_time | 下单时间 |
pay_order_time | 支付时间 |
pay_order_amt | 支付金额(元) |
从表结构可以看出,该表存储的内容是买家每下单一种服务时产生的相关信息记录。为了站在订购者的角度去分析数据(如:当月各个渠道总支付金额数),理论上可以设计一张订购者维表,存储订购者的相关属性(性别、年龄、渠道来源、电话、地区等等)。
而在这张事实表中,粒度即为订单ID。
那么在上面这张事实表中,哪个字段看上去像维度关键字,却又不需要为它单独设计一张维表呢?
如果设计一张服务维表是否可行,包含字段(服务ID、服务名称、服务类型、服务上架时间、服务时长等等)?
退化维度是这样一种维度:过于简单或诸如订单ID这种量级很大的维度,不值得单独创建一个维表进行存储。
那么,订单ID和服务ID(服务维表可剔除,维度属性可放在事实表中)都可以作为退化维度
但这个事务编号仍然十分有用,因为它可以作为组关键字而将单个事务中处理的明细集中在一起:如统计各项服务的订单个数,severice_id作为组关键字,汇总该维度下的订单个数count(order_id)
三、退化维度优点
减少事实表和维度表的关联
该技术减少维度的数量, 简化维度数据仓库模式。 简单的模式比复杂的更容易理解, 也有更好的查询性能。
如果存在退化维,ETL的过程会变得非常容易
可以让group by 等操作变得更快
当一个维度没有数据仓库需要的任何数据的时候就可以退化此维度,需要把退化的相关数据迁移到事实表中,然后删除退化的维度。退化维度没有对应的维表,但可以获取与之相关的事实,如上订单号对应的订购者,服务对应的订购金额等。
下面是其他角度的一个解释:
当一个维度没有数据仓库需要的任何数据的时候就可以退化此维度,需要把退化的相关数据迁移到事实表中,然后删除退化的维度。与其他存储在维度表中的维度一样,退化维度也可以进行事实表的过滤查询,实现聚合操作等。那么究竟怎么定义退化维度呢?比如说订单id,这种量级很大的维度,没有必要用一张维表来进行存储,而我们进行数据查询或者数据过滤的时候又非常需要,所以这种就冗余在事实表里面,这种就叫退化维度。注意:citycode这种我们也会冗余在事实表里面,但是它有对应的维度表,所以它不是退化维度。
Kimball书中对退化维度的描述为:操作型事务控制号码,例如:订单号码,发票号码,提货单号码通常产生空的维度,经常保存为事实表中的退化维度。退化维度是没有对应维度表的维度键。
维度退化在事实表中有利于使用,一般一个维度键都有对应的维表,如果退化在事实表中,可以减少关联次数,并且退化维度可以用于group by操作,进行分组统计。
核心理解:退化维度没有对应对应的维表,没有修饰它的属性,但是呢,通过它你可以获取一些内容,一些事实,比如说订单编号,你可以通过它获得这个订单里面包含哪些商品,对应的付款人是谁等。注意,对于不变维度,可以进行退化,对于缓慢变化维度,视具体情况而定,如果忽略缓慢变化维度的影响可以退化,否则不建议退化。
如果维度表的数据一直要更改,比如国家维度,每个国家id对应的国家某信息一直要变更,则不建议进行维度退化,因为退化后每次变更会一发而动全身,下游也会进行相对更多的变化。