zoukankan      html  css  js  c++  java
  • hive中拉链表

    在有些情况下,为了保持历史的一些状态,需要用拉链表来做,这样做目的在可以保留所有状态的情况下可以节省空间。

    拉链表适用于以下几种情况吧

    数据量有点大,表中某些字段有变化,但是呢变化的频率也不是很高,业务需求呢又需要统计这种变化状态,每天全量一份呢,有点不太现实,

    不仅浪费了存储空间,有时可能业务统计也有点麻烦,这时,拉链表的作用就提现出来了,既节省空间,又满足了需求。

    一般在数仓中通过增加begin_date,en_date来表示,如下例,后两列是start_date和end_date.

    1  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
    1  2016-08-20  2016-08-21  支付 2016-08-21  2016-08-21
    1  2016-08-20  2016-08-22  完成 2016-08-22  9999-12-31
    2  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
    2  2016-08-20  2016-08-21  完成 2016-08-21  9999-12-31
    3  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-21
    3  2016-08-20  2016-08-22  支付 2016-08-22  9999-12-31
    4  2016-08-21  2016-08-21  创建 2016-08-21  2016-08-21
    4  2016-08-21  2016-08-22  支付 2016-08-22  9999-12-31
    5  2016-08-22  2016-08-22  创建 2016-08-22  9999-12-31
    

    begin_date表示该条记录的生命周期开始时间,end_date表示该条记录的生命周期结束时间;

    end_date = ‘9999-12-31’表示该条记录目前处于有效状态;

    如果查询当前所有有效的记录,则select * from order_his where dw_end_date = ‘9999-12-31′

    如果查询2016-08-21的历史快照,则select * from order_his where begin_date <= ‘2016-08-21′ and end_date >= ‘2016-08-21’

    再简单介绍一下拉链表的更新:

    假设以天为维度,以每天的最后一个状态为当天的最终状态。

    以一张订单表为例,如下是原始数据,每天的订单状态明细

    1	2016-08-20	2016-08-20	创建
    2	2016-08-20	2016-08-20	创建
    3	2016-08-20	2016-08-20	创建
    1	2016-08-20	2016-08-21	支付
    2	2016-08-20	2016-08-21	完成
    4	2016-08-21	2016-08-21	创建
    1	2016-08-20	2016-08-22	完成
    3	2016-08-20	2016-08-22	支付
    4	2016-08-21	2016-08-22	支付
    5	2016-08-22	2016-08-22	创建
    

    根据拉链表我们希望得到的是

    1  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
    1  2016-08-20  2016-08-21  支付 2016-08-21  2016-08-21
    1  2016-08-20  2016-08-22  完成 2016-08-22  9999-12-31
    2  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
    2  2016-08-20  2016-08-21  完成 2016-08-21  9999-12-31
    3  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-21
    3  2016-08-20  2016-08-22  支付 2016-08-22  9999-12-31
    4  2016-08-21  2016-08-21  创建 2016-08-21  2016-08-21
    4  2016-08-21  2016-08-22  支付 2016-08-22  9999-12-31
    5  2016-08-22  2016-08-22  创建 2016-08-22  9999-12-31
    

    可以看出 1,2,3,4每个订单的状态都有,并且也能统计到当前的有效状态。

    本例以hive为例,只考虑到实现,与性能无关

    首先创建表

    CREATE TABLE orders (
    orderid INT,
    createtime STRING,
    modifiedtime STRING,
    status STRING
    ) row format delimited fields terminated by '	' 
    
    
    CREATE TABLE ods_orders_inc (
    orderid INT,
    createtime STRING,
    modifiedtime STRING,
    status STRING
    ) PARTITIONED BY (day STRING)
    row format delimited fields terminated by '	' 
    
    
    CREATE TABLE dw_orders_his (
    orderid INT,
    createtime STRING,
    modifiedtime STRING,
    status STRING,
    dw_start_date STRING,
    dw_end_date STRING
    ) row format delimited fields terminated by '	' ;
    

    首先全量更新,我们先到2016-08-20为止的数据。

    初始化,先把2016-08-20的数据初始化进去

    INSERT overwrite TABLE ods_orders_inc PARTITION (day = '2016-08-20')
    SELECT orderid,createtime,modifiedtime,status
    FROM orders
    WHERE createtime < '2016-08-21' and modifiedtime <'2016-08-21';
    

    刷到dw中

    INSERT overwrite TABLE dw_orders_his
    SELECT orderid,createtime,modifiedtime,status,
    createtime AS dw_start_date,
    '9999-12-31' AS dw_end_date
    FROM ods_orders_inc
    WHERE day = '2016-08-20';
    

    如下结果

    select * from dw_orders_his;
    OK
    1  2016-08-20  2016-08-20  创建 2016-08-20  9999-12-31
    2  2016-08-20  2016-08-20  创建 2016-08-20  9999-12-31
    3  2016-08-20  2016-08-20  创建 2016-08-20  9999-12-31
    

    剩余需要进行增量更新

    INSERT overwrite TABLE ods_orders_inc PARTITION (day = '2016-08-21')
    SELECT orderid,createtime,modifiedtime,status
    FROM orders
    WHERE (createtime = '2016-08-21'  and modifiedtime = '2016-08-21') OR modifiedtime = '2016-08-21';
    
    select * from ods_orders_inc where day='2016-08-21';
    OK
    1  2016-08-20  2016-08-21  支付 2016-08-21
    2  2016-08-20  2016-08-21  完成 2016-08-21
    4  2016-08-21  2016-08-21  创建 2016-08-21
    

    先放到增量表中,然后进行关联到一张临时表中,在插入到新表中

    DROP TABLE IF EXISTS dw_orders_his_tmp;
    CREATE TABLE dw_orders_his_tmp AS 
    SELECT orderid,
    createtime,
    modifiedtime,
    status,
    dw_start_date,
    dw_end_date 
    FROM (
        SELECT a.orderid,
        a.createtime,
        a.modifiedtime,
        a.status,
        a.dw_start_date,
        CASE WHEN b.orderid IS NOT NULL AND a.dw_end_date > '2016-08-21' THEN '2016-08-21' ELSE a.dw_end_date END AS dw_end_date 
        FROM dw_orders_his a 
        left outer join (SELECT * FROM ods_orders_inc WHERE day = '2016-08-21') b 
        ON (a.orderid = b.orderid) 
        UNION ALL 
        SELECT orderid,
        createtime,
        modifiedtime,
        status,
        modifiedtime AS dw_start_date,
        '9999-12-31' AS dw_end_date 
        FROM ods_orders_inc 
        WHERE day = '2016-08-21' 
    ) x 
    ORDER BY orderid,dw_start_date;
    
    INSERT overwrite TABLE dw_orders_his
    SELECT * FROM dw_orders_his_tmp;
    

    在根据上面步骤把2016-08-22号的数据更新进去,最后结果如下

    select * from dw_orders_his;
    OK
    1  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
    1  2016-08-20  2016-08-21  支付 2016-08-21  2016-08-21
    1  2016-08-20  2016-08-22  完成 2016-08-22  9999-12-31
    2  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-20
    2  2016-08-20  2016-08-21  完成 2016-08-21  9999-12-31
    3  2016-08-20  2016-08-20  创建 2016-08-20  2016-08-21
    3  2016-08-20  2016-08-22  支付 2016-08-22  9999-12-31
    4  2016-08-21  2016-08-21  创建 2016-08-21  2016-08-21
    4  2016-08-21  2016-08-22  支付 2016-08-22  9999-12-31
    5  2016-08-22  2016-08-22  创建 2016-08-22  9999-12-31
    

    至此,就得到了我们想要的数据。

  • 相关阅读:
    Flutter 中那么多组件,难道要都学一遍?
    【Flutter实战】自定义滚动条
    Python 为什么只需一条语句“a,b=b,a”,就能直接交换两个变量?
    一篇文章掌握 Python 内置 zip() 的全部内容
    Python 3.10 的首个 PEP 诞生,内置类型 zip() 迎来新特性
    Python 3.10 版本采纳了首个 PEP,中文翻译即将推出
    Python 为什么不支持 i++ 自增语法,不提供 ++ 操作符?
    Python 为什么推荐蛇形命名法?
    Python 为什么没有 main 函数?为什么我不推荐写 main 函数?
    Python 为什么不用分号作终止符?
  • 原文地址:https://www.cnblogs.com/wujin/p/6121754.html
Copyright © 2011-2022 走看看