• Hive学习小记-(10)hive增量下发的变化流水表如何做update操作


    场景

    有一张明细事务级别的流水表,主键是事件流水号srl_id, 该表每天采集当天新增及变化的事件下发,上游下发文件分区日期prt_dt. 

    存在这样的情况,某个流水号srl_id在20210101发生,会在prt_dt=20200101的分区首次下发,若之后在20200105发生改变,在prt_dt=20200105会再次下发。

    每个流水号都有一个estb_dt,即首次发生日期,同一srl_id,该日期值不变。

    需求是:下游每天接收处理数据,对在20200105发生改变的srl_id,要在下游应用保留分区20200101中更新,即让这个发生改变的流水号srl_id信息在下游第一次落地的分区日期始终保持最新的状态,这个下游分区其实等价于estb_dt首次发生日期。

    分析

    一般的写法往往有全表扫描:

    insert overwrite  table 原表
    select  a.* from 原表 a  left join 增量表 b on a.业务不会变化的字段如srl_id=b.业务不会变化的字段 where b.业务不会变化的字段 is null
    union all select * from 增量表;
    insert overwrite table full_data_table -- 全量
    select
        a.pk_col
        a.data_col 
    from full_data_table a    
    left join inc_data_table b            --数据量很大,会造成全局扫描
    on a.pk_col = b.pk_col and b.date=execution_date
    where a.date<execution_date
      and b.pk_col is null       --没受影响的数据
    
    union all 
       select 
            cc.data_col 
        from inc_data_table cc
        where date=execution_date;

    对历史分区的有更改数据做UPDATE操作;难点在于如何避免全表扫描找有更改的srl_id

    优化方法

    1. tb_a下游累数分区全量表,选择相对业务srl_id不变的时间字段estb_dt做分区字段,每个分区存放当天estb_dt的srl_id数据;

    2. 当天下发的新数据,包含新增业务数据+新增更改数据,建临时增量表 tb_b,也以estb_dt做分区(这里是否有必要?没必要,这里左表大数据量的关联键一定要是分区键,不能全表扫描,但b表只要数据量足够小默认放进内存就行,如果b表没法小怎么办?)

    3.通过left semi join 定位出增量表影响到的分区,关联字段取分区字段,避免全表扫描(bug: 1.这里增量临时分区表是否必要,下发增量数据不以estb_dt分区,而是以prt_dt分区会避免全表扫描吗?可的,其实主要是避免a表全表扫描,b表起过滤作用,足够小可以放进内存就可以)

    4.通过left join去除受影响分区中要发生变化的数据,这部分即无变化的历史数据

    5.再union all当天增量下发数据:即新增业务数据+变更业务数据,就是目标数据

    6.这里脚本都未加时间限制,加了时间限制后支持历史执行日期重新调度

    一些小疑问:这里若A是增量表,B是全量表也可以操作,只是left semi join会变成左表小,右表大,这样性能会更好吗?

    -- 创建增量数据临时表
    create table if not exist tb_b ...partition by(esdb_dt int '首次业务日期')
    insert overwrite tb_b partition(esdb_dt) select ...
     
    --当天数据加工
    insert overwrite tb_a partition(estb_dt)
    select
      a.srl_id
      a.estb_dt
    from tb_a a  -- 全量
    left semi join tb_b b1  -- 增量,用left join on key防止全表扫描
      on a.estb_dt=b1.estb_dt     -- 获取历史表受影响的数据分区
    left join tb_b b   -- 增量
      on a.srl_id = b.srl_id
    where b.srl_id is null        -- 过滤掉b表出现变更的记录,得到未变更历史
    
    union all
    select                             --加上增量表(新增srl_id+变更srl_id)
      b.srl_id
      b.estb_dt
    from tb_b b  -- 增量

    一些其他帖子

    full join :https://blog.csdn.net/magicharvey/article/details/20692829

                       https://my.oschina.net/sniperLi/blog/755273

    业务不会变化的字段:https://blog.csdn.net/iteye_3893/article/details/82651247?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

    每次只更新发生变化的分区:https://blog.csdn.net/wujiandao/article/details/80413661

    rownumber:http://www.fengxiaokai.cn/archives/27

  • 相关阅读:
    PAT 天梯赛 L1-002 【递归】
    HDU_2717_Catch That Cow
    Stock Exchange (最大上升子子串)
    Lorenzo Von Matterhorn(map的用法)
    Ignatius and the Princess IV (简单DP,排序)
    投掷硬币(概率dp)
    Find The Multiple (DFS递归)
    24 Game
    棋盘问题
    linux上的文件服务
  • 原文地址:https://www.cnblogs.com/foolangirl/p/14222561.html
Copyright © 2020-2023  润新知