表同步方式
个人理解
维表肯定都是全量导入
特殊表基本在很长一段时间不变化,初始化即可
新增表只有一个create_time这个字段,所以是不支持修改的。数据一旦产生就不能改,只能追加
新增变化表,只有两个大头,用户和订单
订单表存在一个order_status,很有可能发生变化,而订单详情表order_status都是新增的所以没有变化。
周期型事实表和事务型事实表区别
如图购物车表是周期型事实表,评论表是事务型事实表。因为购物车里面存在会随时间变化的字段,例如购物车数量,所以没有办法做增量同步。所以每天做一次全量的快照导入。但是数据量会越来越大,所以一般保留7天
一般的周期型事务表有
购物车表
收藏表
累积型事实表(有则改之无则加勉)
难点
所谓累积型事实表,存在一个事件的概念,例如一张优惠券领用表,从开始领用,到下单使用,再到支付使用,存在3个事件周期,所以无法通过操作时间来获取分区,因为我们想要得到历史和最新更改的数据。输入如图
1 3.8号数据
2 3.9号数据
3 3.10号数据
这里每天都是来自ods层的数据,也就是单天操作数据的分区表数据表。
我们想得到的输出如图
显然根据操作时间分区是无法得到这样的数据的,所以累积型事务表一般选择事务开始时间作为分区字段,在这里我们选择优惠券领用时间作为dwd层的分区字段
说白了就是旧dwd表和新表做full outer join ,有则改之无则加勉。
1查旧表
select
说白了就是查出非2020-03-10,get_time的所有数据
2查新表
select
这里查出的是10号的变化新增表
3对新旧两边做join操作,这里因为要保留所有的信息,所以选择根据二者的行id进行full out join,这里的id是uuid唯一配对的,两张表没有的值会补null。这时候要思考取旧表的字段,还是新表的字段。首先当然是取新表字段。但是旧表有,新表没有的值我们也要覆盖处理,所以只要新表为空,且旧表不为空的值,就用旧表值覆盖,这个条件是肯定成立的,因为两边都为空是不可能出现在join的结果的。
if(new.id is null,old.id,new.id)
完整sql
set
注意,动态分区要加
set hive.exec.dynamic.partition.mode=nonstrict;
select字段最后加动态分区字段
date_format(if(new.get_time isnull,old.get_time,new.get_time),'yyyy-MM-dd')
sqoop参数解析
sqoop导入脚本需要注意的点
- --target-dir 每张表每天一个文件夹
- --delete-target-dir 判断输出路径有没有,有的话删掉
- --query "$2 and $CONDITIONS"查询条件and $CONDITIONS是固定语法
- --num-mappers 并行度
- --fields-terminated-by 输出分隔符
- --compress 支持压缩
- --compression-codec lzop 压缩方式
- --null-string 'N' hive底层用'N'表示NULL。mysql底层用'NULL'表示NULL,mysql的null直接导入会被认为是字符串null,所以导入hdfs要采用
- --null-non-string 'N'
给导入的表创建索引,支持对应切片
hadoop jar /opt/module/hadoop-2.7.2/share/hadoop/common/hadoop-lzo-0.4.20.jar
com.hadoop.compression.lzo.DistributedLzoIndexer
/origin_data/gmall/db/$1/$do_date
Sqoop User Guide (v1.4.7)sqoop.apache.org
导入sql条件
全量导入,直接查表即可,记得加条件才可以用sqoop的条件选项并且防止sql注入
where 1=1
新增表导入,条件
where
date_format(operate_time,'%Y-%m-%d')='$do_date'
新增及变化导入,
where date_format(create_time,'%Y-%m-%d')='$do_date'
or date_format(operate_time,'%Y-%m-%d')='$do_date')