离线数仓(六)【ODS 层开发】

2024-03-10 1725阅读

温馨提示:这篇文章已超过442天没有更新,请注意相关的内容是否还可用!

前言

1、ODS 层开发

ODS层的设计要点如下:

(1)ODS层的表结构设计依托于从业务系统同步过来的数据结构(JSON/CSV/TSV)。

(2)ODS层要保存全部历史数据,故其压缩格式应选择高压缩比的算法,此处选择gzip。

(3)ODS层表名的命名规范为:ods_表名_单分区增量全量标识(inc/full)。

注意:ODS 层的表都是分区表,因为我们每天都会有数据被采集到数仓,所以我们的表是按照日期分区的,每天一张表。

我们当前保存在 HDFS 路径下的数据主要有两类:log 和 db,log 目录下存放是我们从 Flume 传过来的用户行为日志文件,我们已经用 gzip 压缩过了,可以通过下面的命令查看:

hadoop fs -cat /origin_data/gmall/log/topic_log/2020-06-14/* | zcat

离线数仓(六)【ODS 层开发】

        可以看到我们的格式是一个 JSON 格式,那我们要建表的话就得考虑怎么把 JSON 格式的数据映射到我们的 Hive 表中了。

        对于 db 目录下的文件主要有两类:DataX 同步过来的以 "full" 为目录后缀的全量业务数据和 Maxwell 同步过来的首日全量数据和以 "inc" 为目录后缀的增量业务数据。

hadoop fs -cat /origin_data/gmall/db/activity_rule_full/2020-06-14/* | zcat

离线数仓(六)【ODS 层开发】

可以看到 DataX 传输过来的文件是 ".tsv" 文件,我们将来只要拿 "\t" 分隔即可。

hadoop fs -cat /origin_data/gmall/db/comment_info_inc/2020-06-14/* | zcat

离线数仓(六)【ODS 层开发】

可以看到,拿 Maxwell 同步过来的数据和 Flume 一样,都是 JSON 格式的。 

1.1、用户行为日志表

1.1.1、ROW FORMAT 和 STORE AS 

打开 Hive 官网 -> LanguageManual -> DDL -> JSON

离线数仓(六)【ODS 层开发】

查看 Hive 3.x 版本支持的通过解析 JSON 映射表的语法:

CREATE TABLE my_table(a string, b bigint, ...)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.JsonSerDe'    -- 声明行的格式
STORED AS TEXTFILE;    -- 声明怎么解析文件

        这里的 ROW FORMAT 和 STORE AS 都是 Hive 建表是所必须指定的,只不过 Hive 帮我们简化了这部分语法:

      ROW FORMAT :用 DELIMITED 关键字表示对文件中的每个字段按照特定分割符进行分割用 SERDE 关键字来指定 Hive 内置的 SERDE 或者 用户自定义的 SERDE。

       STORE AS :用 STORED AS + 简写文件格式来指定 InputFormat 和 OutputFormat ,默比如 TextFileInputFormat 和 TextFileOutputFormat 可以用 STORE AS TEXTFILE 来表示。

Hive SerDe

离线数仓(六)【ODS 层开发】

        Hive 的 ROW FORMAT 的 SERDE 属性指定了 Hive 的序列化器和反序列化器,映射 HDFS 文件时,使用反序列化器进行解析,写出文件时使用序列化器来封装数据。

1.1.2、复杂数据类型

        对于用户行为日志,它的存储格式是 json 格式,那我们就需要把它的每个字段映射到我们 Hive 表中。首先回顾一下 Hive 的三种复杂类型:

离线数仓(六)【ODS 层开发】

  • array
    • 声明:array
    • 取值:arr[0]
    • 构造:array(val1,val2...),split(),collect_set()
  • map
    • 声明:map
    • 取值:map[key]
    • 构造:map(key1,val1,key2,val2...)
  • struct
    • 声明:struct
    • 取值:struct.id
    • 构造:named_struct(name1,val1,name2,val2...)

    离线数仓(六)【ODS 层开发】

            对于上面的 common 字段,它虽然是键值对格式,但是我们不能使用 map ,因为 map 的 value 是同一数据类型,而我们这里的 common 字段不同键的值有的是 int 有的是 string。所以我们使用 struct。

    离线数仓(六)【ODS 层开发】

            对于 displays 字段,由于它存储的是数组类型,然后数组嵌套键值对,所以我们需要使用 array(struct) 的嵌套类型。

    1.1.3、设计日志表

    DROP TABLE IF EXISTS ods_log_inc;
    CREATE EXTERNAL TABLE ods_log_inc
    (
        `common`   STRUCT COMMENT '公共信息',
        `page`     STRUCT COMMENT '页面信息',
        `actions`  ARRAY COMMENT '动作信息',
        `displays` ARRAY COMMENT '曝光信息',
        `start`    STRUCT COMMENT '启动信息',
        `err`      STRUCT COMMENT '错误信息',
        `ts`       BIGINT  COMMENT '时间戳'
    ) COMMENT '活动信息表'
        PARTITIONED BY (`dt` STRING)
        ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.JsonSerDe'
        LOCATION '/warehouse/gmall/ods/ods_log_inc/';
    

    注意:我们数仓建的基本都是外部表,防止误删数据!

    离线数仓(六)【ODS 层开发】

    gzip 和 bzip2 格式的文件可以直接以 textfile 的格式来 load ,而不需要在建表时指定压缩格式(其实就是指定 STORE AS )。

    但是其他压缩格式是不行的,比如 LZO 压缩的话,必须指定 STORE AS 的 InputFormat 和 OutputFormat :

    CREATE EXTERNAL TABLE IF NOT EXISTS hive_table_name (column_1  datatype_1......column_N datatype_N)
             PARTITIONED BY (partition_col_1 datatype_1 ....col_P  datatype_P)
             ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
             STORED AS INPUTFORMAT  \"com.hadoop.mapred.DeprecatedLzoTextInputFormat\"
                       OUTPUTFORMAT \"org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat\";

    1.1.4、装载脚本

    我们的日志数据每天都要 load 到一张新的分区表中。

    load data inpath '/origin_data/gmall/log/topic_log/2020-06-14' into table ods_log_inc partition(dt='2020-06-14')
    

    剩下的明天补

VPS购买请点击我

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

目录[+]