数仓实现过程
1、了解需求(包括原始数据结构)
2、提取指标(事实表)、维度(维度表)
3、分层设计
4、建模
5、分层实现
1、了解需求(包括原始数据结构)
2、提取指标和维度
3、设计分层
ODS:保留最完整的原始数据、外部表
DW:
新零售项目:DWD、DWB、DWS、DM(教育项目:DWD、DWM、DWS)
DWD:保证数据高质量,进行清洗转换;
DWB:明细宽表,降维冗余,雪花模型——》星型模型;
DWS:日统计宽表,按天进行轻度聚合;
DM:数据集市,总累积、年、季度、月、周、天;等同于教育项目的DWS层;
RPT/APP/DA:OLAP应用层
教育项目分层:ODS、DWD、DIM、DWM、DWS、APP
DIM:维表层,维度表,维度数据的统一口径;
DWM(middle):中间组件层:1、明细宽表,减少join;2、轻度聚合,日统计宽表;
DWS(service):数据集市:粗粒度的聚合汇总
4、建模
ODS-》字段保持和原始数据一致,增加抽取日期作为分区;
DWD-》1、增加转换后的字段:年、季度、月、周;2、拉链表字段:生效日期、封链日期;
DWB(教育DWM)-》将关联表的字段,都放进来;关系紧密经常一起使用、副表数据量不能比主表大太多;
DWS(教育DWM)-》按照主题需求统计,字段包含了指标、维度、group_type;
DM (教育DWS)-》按照主题需求统计,字段包含了指标、维度、group_type、年、季度、月、周、日、time_type;
RPT(教育APP)-》个性化的需求,按照需求来走;
5、实现抽取计算
5.1、根据分层,进行功能实现
5.2、实现过程中,出现问题解决问题
ODS-》
sqoop 首次:select * from table where 1=1 and $CONDITIONS
循环:select * from table where (create_time between '2022-02-14 00:00:00' and '2022-02-14 23:59:59')
or
(update_time between '2022-02-14 00:00:00' and '2022-02-14 23:59:59')
and $CONDITIONS
DWD-》
清洗:根据不同表的业务,进行针对性的过滤:where buy_user is not null
转换:枚举值转换、时间格式、单位统一、脱敏、Json拉平
拉链表:生效日期、封链日期。会更新的表才需要用。查询拉链表和更新拉链表。
DWB(教育DWM)-》
明细宽表,降维冗余。
Left Join & Full Join ——》 数据重复
关联原则:关系紧密经常一起使用、副表数据量不能比主表大太多、不断变化的
主表 left join 副表 on ...
left join 副表 on ...
left join 副表 on ...
left join 副表 on ...
自关联:涉及到多层自关联的表,需要将各层均冗余到宽表中。 from table a left join table b on a.parent_id=b.id
DWS(教育DWM)-》
日统计宽表,按天进行轻度聚合
去重的方法: 1、distinct:针对单个字段去重;2、groupby:对全局数据生效,影响分组和聚合的结果;3、row_number+partitionby:对全局数据生效,不影响分组和聚合的结果
-- ==================城市
with rn_base (
select
row_number() over(partition by order_id) rn
from dwb
)
select
count(order_id), sum(order_price)
from rn_base
where rn=1
group by dt, city;
-- ==================商圈
with rn_base (
select
row_number() over(partition by order_id) rn
from dwb
)
select
count(order_id), sum(order_price)
from rn_base
where rn=1
group by dt, trade_area;
-- ==================
………………
grouping sets:
场景:1、多个groupby;2、数据来源要一致。
优点:1、合并后sql简短;2、只读取一次硬盘数据,性能提升。
DM -》
年、季度、月、周、日
-- =====time_type:year group_type:all
with groupby as
(
select sum(order_price),
case when grouping(trade_area)=0
then 'trade_area'
when grouping(city)=0
then 'city'
END as group_type_new
-- group_type:all、city、trade_area...
from dws
-- where dws.group_type='all'
group by
grouping sets (
(year),
(year, city),
(year, trade_area),
(year_month),
(year_month, city),
(year_month, trade_area),
......
)
)
SELECT * from groupby
-- 天数据的分组类型 = 年数据的分组类型
where dws.group_type = group_type_new;
-- 总累积、首末日期
-- 累加的计算方式,不止是总累计值可以用、年、季度等都可以用:取舍在于性能和复杂度之间
DM旧累计值 + 昨天新数据 = 新累计值
性能更高、过程复杂;
max(date) 首次日期
min(date) 末次日期
RPT-》个性化操作