数据仓库维度建模
雪花模型
星型模型
星座: 多个事实表
问题:
1、数据仓库,不针对某一个分析主题,而是有多个分析主题,即多个事实表,维度表怎么设计?
2、即使是同一个分析主题,也可能存在多个事实表,维度表如何设计?多个时间维度?
无论星型模型、雪花模型还是星座模型,都是针对维度上的区别而来,星座模型实质上还是星型模型,
只是共用了维度。
维度设计
代理键:
维度表中唯一有一个能够唯一标识一行记录的列,通过该列维护维度表和事实表的关系,一般在
维度表中业务主键符合条件可以当作维度主键。
是由数据仓库处理过程中产生的、与业务本身无关的、唯一标示维度表中一条记录并充当维度表
主键的列,也是描述事实表和维度表关系的纽带,所以在设计有代理键的维度表中,事实表中的
关联键是代理键而不是原有的业务主键,即业务关系是靠代理键维护,这样有效避免源系统变化
对数仓数据的影响。
在实际业务中,代理键通常是数值型,自增的值。
问题: 传统数据库有自增id默认功能,但hive怎么生成自增的代理键?
row_number() over (partition by .. order by ..) as rn
问题:
1、当整合多个数据源的维度时,不同数据源的业务主键重复怎么办?
2、涉及维度拉链表时,同一主题对调记录,业务键重复怎么办?
S1.goods
id | name | note |
---|---|---|
1 | da | finc |
2 | jiang | fin |
S2.goods
id | name | note |
---|---|---|
1 | daanhg | fikknc |
2 | uuug | fijjn |
两个系统整合,主键一致,已经不能使用id作为代理键
这种情况下,可以自己维护一个代理键
gid | id | name | note | source |
---|---|---|---|---|
1 | 1 | da | finc | s1 |
2 | 2 | jiang | fin | s1 |
3 | 1 | daanhg | fikknc | s2 |
4 | 2 | uuug | fijjn | s2 |
稳定维度
部分维度表的维度是在维度表产生后,属性是稳定的,无变化的;比如时间维度、区域维度等,针对
这种维度,设计维度表的时候,仅需要完整的数据,不需要天的快照数据,因为当前数据状态即是历史
数据状态。
缓慢渐变维度
维度数据会随着时间发生变化,变化速度比较缓慢,这种维度数据通常称作缓慢变化维;由于数据仓库需要追溯
历史变化,尤其是一些重要的数据,所以历史状态也需要采取一定的措施进行保存。
缓慢变化维解决办法:
1、每天保存当前数据的全量快照数据,该方案适合数据量较小的维度,使用简单的方式保存历史状态。(目前用的比较多的)
2、在维度表中添加关键属性值的历史字段,仅保留上一个的状态值。(应用场景不是特别多)
3、拉链表: 当维度数据发生变化时,将旧数据置为失效,将更改后的数据当作新的记录插入到维度表中,并开始生效,
这样能够记录数据在某种粒度上的变化历史。
拉链表
因为是对维度表做拉链,所以对同一个维度实体必然存在多条记录,此时维度表的原子性主键就不存在了。
id | name | dept | start_date | end_date |
---|---|---|---|---|
1 | zyh | bigdata | 20190202 | 20190208 |
1 | zyh | phoenix | 20190209 | 99991231 |
问题: 拉链表怎么和事实表关联?
答案: 添加代理键
Fact_order(订单)
oid | uid | tm_id |
---|---|---|
1 | 1 | 9 |
2 | 2 | 10 |
Dim_user(用户维度)
uid | id | name | dept | start_date | end_date |
---|---|---|---|---|---|
1 | 1 | zyh | bigdata | 20190202 | 20190208 |
2 | 1 | zyh | phoenix | 20190209 | 99991231 |
问题: 事实表来源与业务事务表,代理键和业务本身没有关系,那么怎么在事实表中装载代理键?
事务表中历史的用户维度id不会发生变化,所以事实表的代理键加载仅发生在新增数据上
案例: 对上述的事实表,装载用户维度代理键(uid)
fact_order(事实表) oid, uid, tm_id...
dim_user(维度表) uid, id, name, dept, start_date, end_date
order(mysql业务表) oid, id, create_time, update_time
采集
--query 'select ... from ... where create_time>20190202' -->> order_inc
装载事实表(hive的join不支持非等值连接)
select
ta.*,tb.uid
from
order_inc as ta
join
dim_user as tb on ta.id=tb.id
and ta.create_time>=tb.start_date and ta.create_time<=tb.end_time;
hive这样写:
select * from
(select
ta.*,tb.uid
from
order_inc as ta
join
dim_user as tb on ta.id=tb.id) tmp
where create_time>=start_date and create_time<=end_time;
代理键优缺点分析:
代理键是维度建模中极力推荐的方式,它的应用能有效的隔离源端变化带来的数仓解雇不稳定问题,
同时也能够提高数据检索性能。
但是如所见,代理键维护成本非常高,尤其是数据装载过程中,对事实表带来了较大的影响,在基于
hive的数据仓库建设影响更加严重,比如代理键的生成、事实表中关联键的装载、不支持非等值关联等问题,
带来ETL过程更加复杂。
故,在大数据体系下,谨慎使用代理键,同时对于缓慢变化维场景,可以考虑空间换取时间,每天保留
维度全量快照;但这样会带来存储成本,根据实际情况衡量。