表同步方式

个人理解

维表肯定都是全量导入

特殊表基本在很长一段时间不变化,初始化即可

新增表只有一个create_time这个字段,所以是不支持修改的。数据一旦产生就不能改,只能追加

新增变化表,只有两个大头,用户和订单

订单表存在一个order_status,很有可能发生变化,而订单详情表order_status都是新增的所以没有变化。


hive建表字段默认非空 hive建表字段设置不为空_hadoop


周期型事实表和事务型事实表区别


hive建表字段默认非空 hive建表字段设置不为空_数据_02


如图购物车表是周期型事实表,评论表是事务型事实表。因为购物车里面存在会随时间变化的字段,例如购物车数量,所以没有办法做增量同步。所以每天做一次全量的快照导入。但是数据量会越来越大,所以一般保留7天

一般的周期型事务表有

购物车表

收藏表

累积型事实表(有则改之无则加勉)

难点

所谓累积型事实表,存在一个事件的概念,例如一张优惠券领用表,从开始领用,到下单使用,再到支付使用,存在3个事件周期,所以无法通过操作时间来获取分区,因为我们想要得到历史和最新更改的数据。输入如图

1 3.8号数据


hive建表字段默认非空 hive建表字段设置不为空_数据_03


2 3.9号数据


hive建表字段默认非空 hive建表字段设置不为空_hive建表字段默认非空_04


3 3.10号数据


hive建表字段默认非空 hive建表字段设置不为空_hadoop_05


这里每天都是来自ods层的数据,也就是单天操作数据的分区表数据表。

我们想得到的输出如图


hive建表字段默认非空 hive建表字段设置不为空_数据_06


显然根据操作时间分区是无法得到这样的数据的,所以累积型事务表一般选择事务开始时间作为分区字段,在这里我们选择优惠券领用时间作为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')