深入解析数据仓库的支架表

前言

支架表是维度设计中非常有意思的一部分,可以说是星型模型和雪花模型的结合;但在大部分维度建模书里都只是简单的一笔带过,实在是过于可惜。

在本文,笔者会对支架表进行详细的介绍,并就其实际应用场景进行探讨。

支架表的诞生

支架表的诞生离不开经典的数仓模型之争——星型模型与雪花模型

星型模型

简单地说,所有的维度表都连在1个事实表上,就是星型模型

星型模型

星型架构是一种非规范化的结构,多维数据集的每一个维度都直接与事实表直接连接

所以数据必然存在一定的冗余

雪花模型

当有一个或多个维表没有直接连接到事实表上,而是通过其他维表连接到事实表上时,其图解就像多个雪花连接在一起,故称雪花模型。

雪花模型是对星型模型的扩展。它对星型模型的维表进一步层次化,原有的各维表可能被扩展为小的事实表,形成一些局部的 " 层次 " 区域,这些被分解的表都连接到主维度表而不是事实表。

对于研发出身的人来说,雪花模型更符合他们的审美——符合范式且不会存在数据的冗余。

雪花模型.png

雪花模型虽然看起来的确舒服,但在数仓中——尤其是Kimball模型——基本无人采用,其对于开发人员的技术要求、ETL的开发、后续的运维都过高;当然主要是没这个必要搞那么复杂。

支架表

虽然上面也提到了,雪花模型不怎么靠谱。但星型模型的冗余有时候的确会有点太多了。

星型模型的冗余.png

虽然我们不推崇雪花模型,但如果一组属性在维度表中出现不止一次时,我们也可以采用受限的雪花模型——也就是支架表

支架表的简单应用.png

可以看到,冗余被大量减少了,结构也看起来舒服多了。

支架表的使用场景

让我们先回顾一下支架表的定义

当一个属性集合(例如日期、地点)在某个维度或多个维度表中反复出现时,就可以考虑使用支架表。

正如 Kimball 自身给出的定义,支架表不能乱用——用多了不就是另一个雪花模型吗?只有在以下条件的时候再考虑:

在单个维度表中反复出现该支架属性时

例如雇员维度表中,同时调用了 出生日期属性入职日期属性 两个日期属性值。

被调用的属性值较多时

即使被反复调用,如果每次都只有1、2个属性值。那笔者还是推荐保留星型模型;不过日期、地点这种太多的就算了。

被多个维度、事实表调用,且被调用时的属性值定义完全相同

例如日期、地点

基本不需要修改或修改频次极小

正如雪花模型的ETL令人头痛一样,支架表的ETL也极为复杂(下面详细说)。

解决一个东西变化修改复杂的最好办法就是避免它变化。

支架表的注意要点

例如时间表——稳定在 24 * 60 * 60 行(粒度在秒时)

更多的表关联

显而易见,支架表的使用会增加查询时的关联数量。一方面会造成查询复杂性的增加。另一方面存在降低性能的风险。

如果数据量不大,可以考虑写个视图来完成维度表和支架表的关联。

缓慢变化维的处理

使用支架表时,一定要特别注意缓慢变化维的相关规则。

例如类型2,有时即使维度行并未发生变化,但也可能需要其对应用类型2变化——因为支架表的类型2变化。

我们举一个简单的例子。

假定location支架表有一个业务地点名称叫 “XR门诊中心”,突然有一天这个地点名称更改为“XR专科门诊”。业务规则规定以前的业绩还是计入之前的名称,但改名后的业绩需要用新的名称来统计。

那我们就需要使用类型2变化来响应,在Location表里添加新行——包含代理键和新的地点名称。同时在user表里添加新行,其中location的代理键自然使用新值。

也可以考虑使用类型1处理——如果业务接受的话。

字段命名的问题

当一个维度对相同的支架表有多个关联关系时(大概率存在),再仔细的开发人员也会犯错。

数仓要求 字段定义——字段名称 最好保证完整的一致(也就是总线矩阵中的一致性维度)。但在维度表和支架表中显然不可能实现——就是会反复调相同属性才会使用支架表。因此这里的字段命名设计ETL设计元数据维护文档管理都尤为的重要。

常见的支架表

日期-date

日期支架表应该是最常用的支架表了——尽管很多时候使用者并不知道这叫支架表

字段名 字段类型 注释 example
day_key int 代理自增ID,用于对外关联 1
full_date date 完整日期 2020-8-21
day_of_week_number int 该周第几日 1
day_of_week_en_name char 该周第几日英文 monday
day_of_week_ch_name char 该周第几日中文 周一
day_of_month int 该月第几日 12
holiday_flag char 是否节假日
weekday_flag char 是否周内
weekend_flag char 是否周末
month_en_name char 所属月英文名 May
month_ch_name char 所属月中文名 五月
month_number int 所属月 5
year int 所属年 2020
quarter int 所属季度 3

日期支架表是最常用的支架表,字段I自然不止这十几个。限于篇幅展示这些,具体内容建议结合业务之余百度。

时间-time

时间支架表经常被人忽略,但却是笔者心中最完美的支架表——永不变化,永远稳定

字段名 字段类型 注释 example
time_key int 代理自增ID 1
second int 59
minute int 59
hour int 23
time_range char 时间段 下午
am_flag char 是否中午12点前
pm_flag char 是否中午12点后

时间支架表被忽视的最主要原因就是不常用......

地点-location

location表的风险点,在于它的更新频率并不低,例如国家 撤县划区 。这种情况下就需要考虑缓慢变化维的处理了。

字段名 字段类型 注释 example
location_key int 代理自增ID 1
location_id int TP系统的自然键 1
gov_code char 官方的地址编码 610502
district char 所在区 临渭区
city char 所在地级市 渭南市
province char 所在省 陕西省
country char 所在国 中华人民共和国
post_code char 邮政编码 714000

location表深究起来字段亦是非常多的,这里只列部分。

其他杂谈

业务驱动

支架表乃至整个数仓的搭建时,都要从业务角度来思考。甚至可以在最后一步再调研已有系统——如果定义的指标、维度合理而目前研发不能满足,那我们需要的是研发补充而非修改指标定义甚至放弃这个指标。数据是产生于各个系统,但产生作用永远是在业务方面。

不要节省资源

很多建模师推荐使用范式建模而非维度建模,这种模型师无疑是优秀的技术架构师——毕竟这年头还有很多系统连范式都没有——但毫无疑问不是优秀的数据架构师。从数据的角度,数据库容量永远是最后考虑的东西。

或者换个角度,告诉老板你可以提升BI展示5倍的速度、日常写SQL效率10倍,但需要目前4倍的硬盘容量。对老板来说这连选择题都不是。

星型模型与雪花模型

或者更准确的说,是维度建模与范式建模。纯粹的范式建模不适用与OLAP系统,纯粹的星型模型也会遇到无数的苦难。根据实际业务情况(而非底层系统)进行适当的妥协——例如微型维度和支架表——才能使你的模型真正靠谱。

你可能感兴趣的:(深入解析数据仓库的支架表)