数仓总结目录:
说说数仓(1) - 什么是数仓
说说数仓(2) - 传统数仓与互联网数仓
说说数仓(3) - 数仓架构
说说数仓(4) - 指标字典
说说数仓(5)-最重要的维度之日期维度
说说数仓(6)-关于命名规范
说说数仓(7)-浅谈数据治理
说说数仓(8)-关于增量
说说数仓(9)-上下游约定
说说数仓(10)-任务注释
就数仓方面来说,用的最多的是GreenPlum,GP是一个分布式可拓展的数据库,当初应该整理些GP的使用小手册的,好久没用感觉都忘了。
很多初学者或者没有做个ETL这件事儿的同学对这个增量是有误解的,尤其是在和业务开发同学对接的时候,他们对这个增量的理解也是有偏差的。
先来说说他们以为的增量是什么。他们以为“增量,就是按照时间增量去拿就好了,增量同步,你就把增量后的数据给我好了,不要总是全量同步。”
按道理说,这么做思路是对的,但是不严谨,而且会出错,下面我们就一步一步看看。
1.什么是增量
增量是相对于全量来说的,它们都是处于“同步数据”这个场景下的,比如说业务系统的数据同步到数仓,数仓的数据同步给业务系统,都会使用同步的方式,这都是相对于我们开发来说的,从数据库级也是可以同步的,这里我们就不介绍了。
全量同步,就是说把数据全部同步过去,100条就同步100条,1万条就同步1万条,1亿条就同步1亿条,大家也应该会发现这种方式存在的问题,在数据量小的时候,全量同步简单方便易执行,而当数据量大了以后,尤其是历史数据不会经常变化的时候,全量同步就会浪费大量的资源和时间,严重影响同步效率。
--全量同步一般先delete,然后insert
delete from tmp_a;
insert into tmp_a xxx;
-- 或者直接 insert overwrite
insert overwrite table tmp_a xxx;
SQL语法可能不太一样,差不多就是这个意思,哈哈
记住一定要删除或者覆盖插入,不然数据可就越来越多了。
选择增量同步的几个场景:
- 数据量很大,而且历史数据不会频繁变化
- 只需要增量数据
使用增量同步,对表有一些要求,比如,需要有create_time,update_time字段
create_time表示记录创建时间,update_time表示记录更新时间,增量的话,只需要把变化的数据拿过来就行了(使用update_time),注意:这里还需要有一个主键,主键是用来覆盖数据的。
这里和不同的业务场景有关系,有的记录创建后不会再更新,类似于流水数据,这种数据直接增量拿过来就好,可以不进行删除操作;
但是有的数据是会更新的,当已经同步过来的数据发生了变化,数仓侧也是需要同步发生变化的。
2. 怎么做增量
增量同步也是要做一次初始化的,初始化是全量来的。
假设我们有这样一张表:
create table tmp_a(
id bigint,
create_time datetime,
update_time datetime
);
一般离线场景下,都会选择在业务量最少的时候去做同步操作,而这个时间大部分都是在半夜凌晨的时候,所以大部分同步都是从0点以后开始,同步昨天的数据,也就是常说的T+1了。
假设3月1号创建了如下4条记录,数仓会在2号凌晨进行同步
2号的时候,新增了1条记录,并且有一条记录更新了,按照增量规则,我们会拿到两条记录
拿到增量数据之后,我们需要将增量的数据合并到我们数仓的表中,
新增的数据,可以直接插入,但是更新的数据,我们需要把原纪录更新掉,或者先删除再插入,以前我们还会记录一个数据插入的状态,如果是更新的,就记一个“update”,如果是插入的就记一个“insert”,到了这里,应该知道为啥需要有主键了吧,如果没有主键,你咋知道这条记录到底变没变过。
使用增量,一般需要两套表,一套表用来存增量数据,一套用来存完整的全量数据。
3. etl_insert_time
不管是增量还是全量,我都比较喜欢加一个时间戳字段,用来标识记录的插入时间,这个尤其是在对比增量数据的时候,排查数据问题很有用。
4. 我们公司的同步机制
我们呢,一创业公司,数据量不算多,使用的都是阿里云的工具,一开始为了方便,所有的数据,都是全量来的,刚看了眼数据量又10几T吧,其中很多是历史数据。
虽然我们是全量来的,但是为了捕捉记录数据的变化,用的是pt(分区)的方式,每天都是一个全量快照,这也是现在存储便宜的一种处理方法,简单粗暴。我刚来的时候,就提过搞成增量,被拒绝了,后来也没有人来搞这个,表太多了,修改起来成本太高。
5. 基于Hive的增量
Hive现在也算是标配了,上面说的增量方案,可能还是基于关系型数据库的,在Hive上,由于运算能力更强大,可以不考虑数据量的问题,所以衍生出来几种方案。主要原因还是Hive上对于delete操作的支持问题,尽量不要有delete。
排序(row_number)
我们依然每天获取增量数据,然后将增量数据插入到每个分区中,每个分区都是当天的增量数据,当然数据变化的话,同一个主键的记录会出现在多个分区中,所以如果我们要获取最新的完整版数据,可以使用row_number根据主键和时间排序,获取最新版本的全量数据full join
使用full join的方式,将增量数据和历史全量数据,进行关联,然后取出最新完整版数据left join + union all
这个和full join的方式类似,感觉这个更美观严谨一些,以前在GP上面做增量也用的这种方式。
6. 拉链表
说到增量,也需要提一下拉链表,拉链表以前用的多一些,感觉在互联网公司用的很少,基本都使用分区的方式处理掉了。
拉链表其实就是记录数据的每一次变化,处理起来稍微有点儿麻烦,这个以前好像写过,等我找找贴过来。