一、维度设计基本概念
1.1 维度与事实
在维度建模中有两个非常重要的概念:维度和事实。与业务过程相关的度量称为事实,维度则是事实的环境描述。
例如在电商场景中,商品维度可包含品牌、类别、款式等维度属性,这些属性帮助企业从不同角度了解商品销售情况;金融领域里,客户维度的属性如年龄、收入、信用评级等,对于风险评估和产品推荐至关重要 。由此可以看出维度是对事实所处环境的补充,二者相互依存才能为复杂的分析场景提供数据支持。
1.2 维度表与事实表
维度表主要用于描述业务过程中的环境和条件,其结构特点通常为窄表。包含主键以及大量描述性字段,如日期维度表中的年、月、日、季度等字段,用于从时间角度描述事实。
事实表则聚焦于业务过程中的度量值,是宽表结构。主键一般由多个维度表的外键组成,形成复合主键,同时包含数值型度量字段,如销售事实表中的售价、商品数量等。
在星型模型中,事实表处于核心位置,直接与各个维度表相连。这种架构下,维度表相对简洁,易用性强,查询性能高,适用于分析场景,例如企业日常运营报表的生成,能快速从各维度(时间、地区、产品等)汇总数据。而雪花模型在星型模型基础上,对维度表进行了规范化处理,部分维度表之间存在层级关系,这种结构降低了数据冗余,但增加了查询的复杂性,适用于oltp场景。
1.3 维度属性
维度属性即维度中的列,是对维度的进一步细化和描述,它提供了关于维度的具体特征和信息。例如,“时间” 维度中 “年”“季度”“月”“日” 等就是时间维度的属性。这些属性可以帮助分析人员从不同的时间粒度来分析数据,比如了解每年、每季度或每月的销售趋势。
1.4 维度表主键
维度表的主键分为:代理主键和业务主键。
代理键是系统生成的无业务含义的唯一标识符,用于处理缓慢变化维等场景;
业务主键是基于业务数据的唯一标识,在某些场景下也可作为维度表主键。业务主键是维度建模中最常用的主键类型。
二、维度设计的步骤
3.1 维度规划
选择或者新建维度。从现有的数据资源中识别和挑选出适合用于维度建模的维度,如果现有的数据中没有合适的维度可用时,根据业务需求和分析目标创建新的维度。比如:为了分析商品的市场趋势,可以新建一个 “商品生命周期阶段” 维度,通过对商品的销售数据、市场竞争情况等进行分析,将商品划分为不同的生命周期阶段,如引入期、成长期、成熟期和衰退期。
3.2 主维表与相关维表的选择
主维表和相关维表可以从业务数据中进行选择,一般来自ods层。
主维表包含了与业务过程相关的主要属性。以销售业务为例,产品维度表可以作为主维表,它存储了产品的基本信息,如产品编号、产品名称、产品类别、品牌等关键属性,这些属性能够全面描述产品这个实体,为分析销售数据提供了关于产品方面的详细信息。
相关维表是与主维表存在关联关系的维度表,它提供了关于主维表某个方面的更详细信息或补充信息。继续以销售业务中的产品维度为例,产品的供应商信息可以存储在一个相关维表中。这个相关维表通过与产品主维表的关联,为产品提供了供应商方面的详细信息,如供应商名称、地址、联系方式等,使得在分析产品相关数据时,能够同时考虑到供应商的因素。
3.3 维度属性确定(设计维度模型)
从主维表与相关维表中提取、生成维度属性,并且进行属性的整合,从而减少主从维表间的关联操作。维度属性的设计一个大的原则就是提高易用性,降低使用成本。
三、维度设计原则和技巧
基于维度设计的步骤已经可以进行维度模型的设计,在设计过程中有诸多行之有效的方法与技巧。
反规范化
维度建模一般采用星型模型,避免复杂的关联操作。数据仓库的使用场景主要为统计分析,对易用性的要求高于存储空间的约束,快速得到分析结果比准守传统的3范式更重要。所以区别于传统oltp场景的雪花模型,星型模型更适合数据仓库。
维度的唯一性
在数仓建设中,不同数据域可能使用同一个维度,比如承保数据域和理赔数据域都会用到保单维度,比如保险类型。这时如果两个数据域分别建设保单维度,可能造成保险类型属性的枚举值存在差异,这时如何需要交叉分析就会存在问题。
相同维度应该避免重复建设,保证维度的唯一性可以保证数据的准确性并大大提升分析效率。
属性的选择
选择高频属性,极少使用的属性可以放到相关维度中或者放弃,因为维度模型的属性个数少则几十多则几百,如果把所有属性都放到维度模型中会造成模型臃肿,且不易于维护。
沉淀通用属性,比如【客户分级】这个属性需要根据客户的消费情况进行等级划分,且经常用于分析场景中,则需要提前进行属性沉淀。
属性富有意义,将编码类属性对应的中文枚举值作为新增属性,编码对于我们分析或者理解数据没有意义,确切的中文描述可以让我们更清晰的理解数据。比如保险类型编码、保险种类编码都应该增加相应的中文属性:保险类型名称、保险种类名称。
属性规范化,统一属性的数据格式、编码规则等。如将不同格式的日期统一为 “yyyy-MM-dd” 格式;金额单位的统一;字段类型的统一等等。
属性的整合
维度整合有两种方式:垂直整合和水平整合。
垂直整合是将多个维表的属性整合到一个维表中,使新维度模型的属性更加丰富。比如保单基本信息表和保单关系人表,可以将保单关系人的属性与基本信息整合到一起。
水平整合是将不同来源的同类数据整合到一张维表中,使维度模型的完整性更高。比如保险数据可以分为财险、车险、农险等等,这些数据分散在不同的业务表中,将这些数据整合到一张表的过程就是水平整合。
属性的拆分
属性拆分有两种方式与整合相对应:水平拆分和垂直拆分。
水平拆分即将不同来源的数据拆分到多个模型的过程。水平拆分通常是因为不同来源的数据各自属性有差异,当业务发生变化时改造成本较高。或者是因为业务相关性较低,不会在分析场景中同时使用,比如一个集团中的各个业务线,各成体系,各业务线不会关心其他业务线的客户信息,这种情况可以水平拆分客户维护。
垂直拆分即将一些属性从主维度模型中剔除,被剔除的属性可以放到相关维度模型中。垂直拆分主要考虑易用性和时效性问题。如果属性过多或者相似属性过多都会给使用者造成困惑,降低使用体验。同时有些属性如果产出时间较晚也应该从主维度模型中剔除。
缓慢变化维
数据仓库的一个重要特性就是数据的缓慢变化,维度同样不是一成不变的,有些场景历史状态对于数据分析非常重要,比如客户的兴趣偏好、所属行业,处理缓慢变化维主要有4种方法:
保留最新状态
只保留最新数据,不保留历史数据。
比如客户维度中的地址信息字段。客户初始地址为:北京市朝阳区,变更后变为:北京市海淀区,表中只保留北京市海淀区。事实表关联客户维度时只能看到最新的地址,不能看到历史地址。
添加维度列
如果只需要保留几个状态的数据,可以使用这种方式。
比如商品维度中的类目字段,随着时间推移类目变化维:类目1 -> 类目2 -> 类目3。可以将创建多个类目字段保存这些历史态类目。
使用拉链表
保留历史状态,并限定状态的时间范围。举例来说订单表中的销售以及销售部门字段,销售存在更换部门的情况,在统计各部门业绩时如果只取最新部门则可能导致其他部门业绩缺失,这时需要使用历史部门信息。
拉链表包含两个时间限定字段:开始日期和结束日期,这两个日期限定了当前记录的生效时间。每次变更都会新增一条记录,并且将历史数据的结束日期更新为t-1。
使用维度快照
维度快照和拉链表一样,也可以保留历史状态,并且限定时间范围。
维度快照的构建方式为每天创建一个快照,每个快照保存了当天的时点状态,并且保留历史快照,使用时事实表使用业务日期关联需要的分区即可。
两者相比较维度快照使用更简单、更容易理解。
细粒度维度整合
如果相关维度的粒度相较于主维度更细,此时不能直接将主维度和相关维度进行整合,整合的方式主要有以下两种:
在主维度中增加多个属性
比如,保险联系人包含投保人、被保人、受益人等,此时如果将联系人信息整合到主维度中,可以在主维度中增加3个属性:投保人姓名、被保人姓名、受益人姓名。这样既保持了主维度的粒度,又保存了联系人的相关属性。
将相关维度属性处理成map
还是保险联系人,将投保人、被保人、受益人的相关属性以kv对的形式保存到主维度的一个map属性中。这样的优势是扩展灵活,且不会导致主维度属性膨胀,但是使用体验不如第一种。
四、退化维度的情况下为什么还需要维度表
很多人有这样的疑惑,既然维度可以退化到事实表,那么直接用事实表当做维度表来用不就可以了吗?
为什么不建议这样做:
1、事实表需要的属性存在差异:
比如将事实表t1作为维度,事实表t2需要属性:代理商等级,但是t1没有这个属性并且也不需要这个属性,那么此时t1就不适合作为维度。好的处理方式是在维度表中添加代理商等级这个属性,事实表t2关联维度表获取此属性。
2、缓慢变化维:
维度的部分属性存在缓慢变化的情况,有些场景需要属性的历史状态,有些需要使用最新状态,这时使用事实表作为维度不适合。
比如:如果部门名称发生变化,如从【销售一部】变更为【销售1部】,从集团的视角分析各部门的业绩则使用最新的部门名称,此时如果没有维度表匹配到最新部门就会出问题。
3、事实表作为维度可能出现循环引用的问题:
比如事实表t1引用了事实表t2的属性,而t2同时也需要t1的某个属性,此时就形成了循环引用,程序无法正常执行。而维度一般来自底层,不容易出现这样的问题。
4、遵循维度建模的规范性,维度和事实有各自的角色,不建议直接使用事实表作为维度使用。
评论