5 最佳实践
5.1 表类型
5.1.1 维度表
-
概念:一般是指对应的一些业务状态,代码的解释表,也可以称作码表
- 作用:查询过程中,用来筛选和组织,例如:可以对数据进行统计,聚合运算,增加我们多维分析的一个性能,使多维分析变得更加灵活些。
5.1.2 事实表
-
概念:一般是指现实存在的业务对象,比如用户,商家等等,是查询结果中的核心数据
- 分类:事务事实表,周期快照事实表,累积快找事实表
5.1.3 事务事实表
-
概念:随着业务不断产生的数据,一旦产生不会变化,如交易流水,操作日志,出库入库记录
- 其他说明:对于数仓来说,建设会比较容易,数仓特征本身是不允许修改的,按顺序追加的表就很好实现了
5.1.4 周期快照事实表
-
概念:随着业务周期型的推进而变化,完成间隔周期内的度量统计,如年、季度累计,例如每天统计一次到今天的累计数值
- 其他说明:使用周期+状态度量的组合,如年累计订单数,天是统计周期,订单总数是度量,是追加到数据的最后面了,不会对我们前面的数据进行修改,甚至比事务事实表压力小,因为数据量没有事务事实表多
5.1.5 累计快照事实表
- 概念:记录不确定周期的度量统计(意味着可能由于生命周期发生改变而产生随机的修改),可修改一般来说对大数据数仓压力就比较大,完全覆盖事实的生命周期,如订单状态表,一般有多个字段去记录生命周期的时间点
例如订单状态表,刚开始下单时,状态为刚下单,未支付,因此支付时间字段为空, 其他的收货时间等字段也是为空,到后续支付后,订单状态会发生改变,到货后,收货时间也发生改变
2.更新方式:
- 上图是用事务事实表实现的,关键时间点更新后,就把数据追加到我们数据后面,但是会产生很多冗余,但是累计快照事实表要求的是只产生一条数据记录
- 下图是全部订单状态也只更新这一条之上,就会产生数据的随机修改,但是在大数据数仓的时候消耗会比较大
- 最佳实现方案:
- 方式一:
- 使用日期分区表,每天分区存储昨天全量数据和当天增量数据,数据类型两种:要么新增要么更新,如果是新增的数据就直接插入到我们今天的时间分区里面,如果是修改的数据,就是与昨天的时间分区里面的数据,然后做一个合并完之后在插入到今天的数据分区中
- 相当于每天都存一份,昨天以及以前数据属于冷数据,不会做更新了,存储下来对性能影响会很大,适用于数据量少的情况
分区表知识补充:(50条消息) 数据库分区概念及简单运用_太白神龙的博客-CSDN博客_数据库分区
-
方式二:
-
依然使用日期分区表,推测下数据的生命周期,比如说订单状态表:从数据生成到生命周期的结束大概生命周期时间大概一个月,存储最大生命周期内(一个月内)的数据,周期外的冷数据要么归档要么删了
- 但是这种方式治标不治本依然需要保留多天一个周期的分区数据,存储消耗依然很大
-
-
方案三:
-
使用日期分区表,以业务实体的结束时间分区,每天分区存放的是当天结束的数据,未结束的设置一个时间非常大的分区,如9999-12-31,存放截止当前未结束的数据
-
数据量不会很大,性能也比较好,无存储浪费,数据全局唯一,不会存多份,无冗余,每天新增的数据跟大分区里面的数据进行对比就可以了,新增的数据跟时间分区里面的数据一对比,生命周期结束就放结束的分区里,没结束就当大分区里面
- 存在问题:业务系统数据有时候无法标识业务实体的结束时间(例如订单结束时间在使用第三方系统下无法返回或者多业务系统集成的数据交换情况),可以采用其他业务系统的结束标志作为业务系统的结束,或最长生命周期时间(例如订单状态最多不超过30天)或前端系统的数据归档时间
-
5.1.6 拉链表
-
概念:拉链表记录每条信息的生命周期,用于保留数据的所有(变更)状态
-
举例:一个待支付,一个已支付状态的订单,并有两个字段:生效开始日期以及生效结束日期,下图当其中一个订单已支付,先结束掉待支付的状态结束掉,在生效结束日期上标注一下,然后追加一条状态进来,状态变成已支付,生效结束日期填最大,这样就能保留这个订单记录的所有一些个时间点
- 对比:不如累积快照事实表
5.2 ETL同步策略
5.2.1 全量同步
-
运用场景:数据初始化装载一定采用的全量同步的方式
- 运用类型:对于结构化数据可以采用JDBC的方式,直接连接到数据库进行抽取,但是对数据库端会带来较大的负载和压力,jdbc是最基本的方式,但是如果是周期时间过长了就可以采用抽取数据库的日志的方式,需要数据库开放相应的功能,例如CDC功能,并使用商用的OGG(oracle常用),或者其他的开源的CDC工具(mysql,sql server),抽取速度快,不会对数据端产生压力
-
补充CDC相关知识:
CDC 是change data capture,即变化数据捕捉。是数据库进⾏备份的⼀种⽅式,常⽤于⼤量数据的备份⼯作。分为⼊侵式的和⾮⼊侵式的备份⽅法,⼊侵式的有基于触发器备份、基于时间戳备份、基于快照备份,⾮⼊侵式的备份⽅法是基于⽇志的备份。
- 其他场景:因为业务,技术原因,给到的数据是全量的(例如数据系统是第三方机构给的),只能使用全量方式,进行周期数据更新,直接覆盖原有数据
5.2.2 增量同步
-
通常对数据库日志进行抽取,对数据库日志按顺序增加的某个时间点之后数据变动更容易追踪到,抽取方式:OGG,或者CDC方式
-
使用JDBC方式的,可以对数据那边增加一个字段,例如create_time创建时间,update_time更新时间,可以利用sql对这些字段进行筛选,筛选出来的数据就是增量的数据了,然后抽取,非结构化数据抽取会更为简单,因为一般抽取工具自带数据监控功能,可以监控出变动的数据
- 新增跟修改的同步方式:
- 同步到数仓时候大多采用merge数据:新增的就insert进去,如果是更新的,就直接对原有数据进行更新就好
- 但是主流大数据平台不支持update方式,于是采用全外连接以及数据全量覆盖方式,在架构那一章有讲
5.3 任务调度
5.3.1 作用
- 可以完成任务的定时执行,而且在集群中有时候要指定特定的节点来完成这些任务,例如数仓的数据抽取,要在业务数据库的节点进行,而且一般会在定时在凌晨执行,数据分析任务会在数据仓库中节点进行了,因此是有定时和执行节点的功能
- 解决单元间依赖的关系:依赖顺序肯定是ETL,然后再是ODS,DWD,ADS
- 总结:所以使用调度系统就可以实现以上的两种功能,一般任务调度系统是有可视化界面的,任务的发布和管理是方便的
5.3.2 常见任务类型
-
Shell脚本:一般用去启动数据仓库的一些集群的组件,比如ETL的采集组件
- Java程序:用于数据清洗或者其他自定义功能
- Mapreduce程序:自带分布式,执行特定功能的时候,吞吐量更高
- SQL脚本:数据库的DDL,以及数据处理任务
5.3.3 常见调度工具
-
Azkaban:功能强大,易用性好一些
- Oozie:老牌