数仓开发详细剖析
1. 数据各层作用
ODS(原始数据层) :日志数据和业务进入数仓后,首先放入该层,建立分区表,防止后续的全表扫描,使用 ORC 列式存储,同时对数据进行压缩,压缩格式采用 LZO,以减少存储空间。
日志:商品列表、商品点击、商品详情;广告;故障;后台活跃、通知;启动表;点赞、评论、收藏等。
业务数据:订单表、用户表、支付流水表、订单详情表、商品表、三级、二级、一级,物流信息(根据产品的来源,有两种,香港特快直送,闪电保税仓。一个从香港发货,一个从内地的保税仓发货)等。
DWD(明细数据层) :对 ODS 层数据清洗(去除空值,脏数据,超过极限范围的数据)。
用户行为数据:自定义 UDF(extends UDF 实现 evaluate 方法),解析公共字段;自定义 UDTF(extends Genertic UDTF->实现三个方法 init(指定返回值的名称和类型)、process(处理字段一进多出)、close 方法),自定义方法的好处在于更加灵活以及方便调试 bug。在自定义函数解析字段时,我们一般建立中间表,存放解析后的表,最后通过 get_json_object 获的我们所需要的字段,建立最终所需表。
业务数据:维度退化+数据清洗(where group by)
脱敏:利用 spark 对手机号、身份证号、银行账号等敏感信息进行脱敏处理。
ETL:通过 HQL、Kettle 对数据进行清洗。清洗标准是核心字段满足业务逻辑要求,去除重复、空值、超过时限等数据。一般清洗率为万分之一,如果大于这个数,需要和前端、javaEE 人员进行沟通。
维度退化:商品表+三级分类、二级分类、一级分类=>商品表,省份+地区表=>省份表,其中我们用到的维度建模理论是星型模型,事实表周围 1 级维度。
LZO 压缩:减少存储空间
列式存储:ORC,增加压缩比
分区表:防止后续的全表扫描
重点重点:DWD 层我们使用的是标准的数仓建模理论
数仓建模怎么建?
我们按照数仓工具箱中的维度建模四步走来建的:
选择业务过程:由于我们公司当时数据量较小,我把 javeEE 涉及的业务表全部导入了,这些表包括实体表,维度表,事务型快照事实表,周期性快照事实表、累积型事实表。过来之后,将这些表作为矩阵的一个列。
声明粒度:粒度一般有:一行信息代表一次、按天、按周、按月等,参考了很多架构之后,我们考虑到后期想要分析更多的指标,只能选择最小的粒度,一行信息代表一次消费。
确认维度:采用标准数仓建模的思维,争取事实表周围都是 1 级维度。我们关系的就是什么时间、什么地点、什么人、具体什么活动、优惠券等主题的维度,同时将跟用户、商品相关的表进行维度退化,尽量把他们降成一级维度。
确认事实:这里我们确定的不是事实表,而是事实表的度量值,我们用到的度量值有订单的个数、订单的金额、下单次数等可以累加的字段。
DWS、DWT(每天的用户行为宽表) :每天的用户行为宽表、商品宽表,相当于一个周期型快照事实表。每天记录用户做了那些事情,商品被下单了多少。
DWS 宽表的字段我们是站在维度的角度来取的,比如站在用户的维度去看待周围的对应事实表,取事实表对应的度量值,取出订单的次数、订单的金额、支付的次数、支付的金额、加入购物车的次数、加入购物车的金额、评论的次数、点赞的次数、收藏的次数等等,将他们组合成为 DWS 层每天发生的事情。
后期我们为了统计的指标,加了一个 DWT 层,DWT 层还是站在维度的角度去看待对应事实表,但是它和 DWS 有略微的区别,现在关注的是这个用户什么时间开始创建的,最后一次登录是什么时候,累计登录多少次,最近 30 天登录多少次等信息。
DWS、DWT 统称为服务层:都是为后面的 ADS 层提供服务的,如果统计的是累积性指标,从 DWT 层拿取数据;如果统计的当天的指标,直接从 DWS 层取对应的数据。DWS 层最大的行为宽表是用户行为宽表,其字段有互动日期、用户 id、用户昵称、注册日期、注册来源、细分渠道、注册省份、评论次数、打赏次数、添加收藏、取消收藏、关注商品、取消关注的商品、关注人、取消关注的人、点不值次数、点值次数、点赞次数、分享次数、爆料数、加购物车数、取消购物车次数等待。DWT 也是用户行为宽表,其字段有互动日期、用户 id、用户昵称、注册日期、注册来源、细分渠道、注册省份、最后一次登录日期、累计登录日期、最近 30 天登录日期等等。
ADS 层:分析了 100 多个指标:包括 日活、月活、周活、留存、留存率、新增(日、周、年)、转化率、流失、回流、七天内连续 3 天登录(点赞、收藏、评价、购买、加购、下单、活动)、连续 3 周(月)登录、GMV、复购率、复购率排行、点赞、评论、收藏、领优惠价人数、使用优惠价、沉默、值不值得买、退款人数、退款率 topN 热门商品、留转 G 复活等。
五、数仓业务详解
我们数据仓库是基于维度建模,主要使用星型模型。
维度表:一般是对事实的描述信息。每一张维表对应现实世界中的一个对象或者概念。例如:用户、商品、日期、地区等。
维表的特征:
维表的范围很宽(具有多个属性、列比较多)
跟事实表相比,行数相对较小:通常< 10 万条
内容相对固定:编码表
事实表:分为事务型事实表(每个事务或事件为单位,一旦产生就固定)和周期型事实表(不会保留所有数据,只保留固定时间间隔的数据,比如每天、每月销售额)以及累积性事实表(累积型快照事实表用于跟踪业务事实的变化,比如订单的状态变化情况)。如果需要后面状态还会改变的就是周期型事实表,一旦确定了,就是事务性事实表。
事实表中的每行数据代表一个业务事件(下单、支付、退款、评价等) 。“事实”这个术语表示的是业务事件的度量值(可统计次数、个数、金额等) ,例如,订单事件中的下单金额。
每一个事实表的行包括:具有可加性的数值型的度量值、与维表相连接的外键、通常具有两个和两个以上的外键、外键之间表示维表之间多对多的关系。
事实表的特征:
非常的大
内容相对的窄:列数较少
经常发生变化,每天会新增加很多。
对于不同的表我们使用不同的同步策略:
同步策略包括全量表,增量表,新增及变化,拉链表
日志表:(商品点击,商品详情,商品详情页表,广告表,错误日志表,消息通知表等)
商品点击:用户的基本信息字段,动作,商品 id,种类等。
商品详情页:入口,上一页面来源,商品 id,加载时间,种类。
广告表:入口,内容,行为,展示风格等。
错误日志:错误详情
消息通知表:通知类型,展示时间,通知内容等
这些记录性质的,都使用每日增量。
业务表:(购物车,评分,评论,订单表,订单详情表,退货表,用户表,商家表,商品分类表(一级,二级,三级),支付流水,物流信息等)
购物车详情:用户 id ,商品 id,商品价格,商家 id ,商品型号,商品分类等 同步策略:这属于周期型事实表,因为它可能会随时改变,所以得用每日新增及变化。
评分表:评分时间,评分用户,评分商品 ,分数等。
同步策略:这是事务性事实表,一般可以用每日增量就可以了,因为评论只能增加,不能修改。
评论表:评论时间,评论用户,评论商品,评论内容。
同步策略:这个跟评分差不多,用每日新增。
订单表:订单状态,订单编号,订单金额,支付方式,支付流水,创建时间等
同步策略:因为订单的状态会随时发生改变,比如下单,支付,商家发货,用户收到货,确认收货,等这一系列的状态会比较长,然后订单也比较多。所以,要做历史快照信息的话,最好使用拉链表。
订单详情表:订单编号,订单号,用户 id,商品名称,商品价格,商品数量,创建时间等。
用户表:用户 id,性别,等级,vip,注册时间等等。
同步策略:因为表不是很大,每次做全量表。
商家表:商家 id,商家地址,商家规模等级,商家注册时间,商家分类信息。
同步策略:每次做每日全量。
总结:
实体表,不大,就可以做每日全量。
对于维度表,比如说商品分类,这种不是很大,也可以做每日全量,有一些不太会发生改变的维度,就可以固定保存一份值,比如说:地区,种族等。
像事务型事实表,比如说交易流水,操作日志,出库信息,这种每日比较大,且需要历史数据的,就根据时间做每日新增,可以利用分区表,每日做分区存储。
像周期型事实表的同步策略,比如订单表,有周期性变化,需要反应不同时间点的状态的,就需要做拉链表。记录每条信息的生命周期,一旦一条记录的生命周期结束,就开始下一条新的记录。并把当前的日期放生效开始日期。
版权声明: 本文为 InfoQ 作者【五分钟学大数据】的原创文章。
原文链接:【http://xie.infoq.cn/article/75f4289fa2c957e63ebdb1b64】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论