前面的笔记地址:
《阿里大数据之路》研读笔记(1)_后季暖的博客-CSDN博客
规范化和反规范化总结就是 规范化让总的单一维度变成多个维度 然后每个维度就是一张表这样 适合OLTP 可以参考三范式 这样是为了减少冗余 比如一个商品有多个类目(类目还有一些相关的字信息字段) ,属于多个行业(行业也带有相关的信息字段)这样可以直接把类目和行业各拆分成一张表 然后在商品表用两张维表的主键引用即可 这样能减少冗余 但是查询会比较缓慢 因为要join
所以反规范化在一定条件下适合OLAP 把这些需要的字段都放在一个表中 冗余就冗余 因为存储成本相对不高
这里解释下一致性上卷 比如一个类目对应多个商品 那么往往类目维度就是商品维度的子集 因为类目维度的字段可能更少 商品维度的字段可能更细一些 但是商品肯定包含它这个类目的所有属性 所以说类目是商品的子集 如果类目维度是公共的 基于类目维度 也可以 大概是这个意思
实际生产中常见的用拉链表处理缓慢变化维:
(2条消息) 拉链表与缓慢变化维_缓慢变化维和拉链表_码皮精的博客-CSDN博客
接下来先详细讲讲代理键的优劣 以及它为什么能处理缓慢变化维
分月做历史拉链表如果这里理解不了 可以看:拉链表(一) - 知乎 (zhihu.com)
看完第一个可以看稍微复杂点的第二个(如何通过binlog采集MySQL的数据并且按月分区的方式实现拉链表):拉链表(二) - 知乎 (zhihu.com)
总结就是
每月2日:首先把上个月未失效的数据的end_date都改为这个月的1号(让它失效)
truncate table user_link_tmp;
-- 这里举例 此时是7月2日 要修正整个6月的数据
-- 把拉链表所有6月30日未失效的数据失效日期改为7月1日
insert into table user_link_tmp;
select
id,
name,
phone,
sing_up_date,
modify_time,
start_date,
'2019-07-01' as end_date
from user_link
where start_date<='2019-06-30'
and start_date>='2019-06-01'
and end_date='9999-12-31'
然后再去查原表(原表不会因为上面的改动而变化!)把上一月的所有未失效的数据归并到这个月1日的分区中,把start_date改为1日,并且把end_date写成9999-12-31
-- 把6月未失效,并且今天也未失效的数据,改为开始日期7月1日,失效日期9999-12-31
insert into table user_link_tmp
select
id,
name,
phone,
sing_up_date,
modify_time,
'2019-07-01' as start_date,
'9999-12-31' as end_date
from user_link
where start_date<='2019-06-30'
and start_date>='2019-06-01'
and end_date='9999-12-31'
and id not in
(
select
id
from user_binlog
where pt_days='2019-07-01'
and type in ('update','delete')
group by id
);
并将1号新增的数据也写入start_date为1日,end_date为9999-12-31的分区
-- 把7月1日新的数据写入到临时表中
insert into table user_link_tmp
select
a.id,
a.name,
a.phone,
a.sing_up_date,
a.modify_time,
'2019-07-01' as start_date,
'9999-12-31' as end_date
from
(
select
id,
name,
phone,
sing_up_date,
modify_time
from user_binlog
where pt_days='2019-07-01'
) a
inner join
(
select
id,
max(modify_time)
from user_binlog
where pt_days='2019-07-01'
and type in ('insert','update')
group by id
) b
on a.id=b.id
and a.modify_time=b.modify_time
这里就有个疑问 之前失效的数据怎么办呢?失效的数据当然还要 不用动就好
接下来把临时表的数据都重新覆盖到拉链表
最后删除上个月所有结束时间为9999-12-31分区的数据
-- 将临时表中的数据覆盖到拉链表中。
insert overwrite table user_link partition(start_date,end_date)
select
id,
name,
phone,
sing_up_date,
modify_time,
start_date,
end_date
from user_link_tmp;
-- 删除临时表中的数据
truncate table user_link_tmp;
-- 删除6月份所有结束时间为9999-12-31分区的数据
alter table user_link_tmp drop if exists partition(stat_date>='2019-06-01' , start_date<'2019-07-01', end_date='9999-12-31' );
如果某个日期同步的数据出现问题需要重跑数据,则需要重跑从当日的同步SQL到当前日期所有的SQL才能保证数据准确。