【数据仓库】Hive 拉链表实践

news/2024/11/6 10:50:16 标签: 数据仓库, hive, hadoop, 人工智能, 数据库, 大数据, 安全

背景

        拉链表是一种数据模型,主要是针对数据仓库设计中表存储数据的方式而定义的;顾名思义,所谓拉链表,就是记录历史。记录一个事务从开始一直到当前状态的所有变化的信息。

        拉链表可以避免按每一天存储所有记录造成的海量存储问题,同时也是处理缓慢变化数据(SCD2)的一种常见方式。

应用场景

        现假设有如下场景:一个企业拥有5000万会员信息,每天有20万会员资料变更,需要在数仓中记录会员表的历史变化以备分析使用,即每天都要保留一个快照供查询,反映历史数据的情况。

        在此场景中,需要反映5000万会员的历史变化,如果保留快照,存储两年就需要2X365X5000W条数据存储空间,数据量为365亿,如果存储更长时间,则无法估计需要的存储空间。而利用拉链算法存储,每日只向历史表中添加新增和变化的数据,每日不过20万条,存储4年也只需要3亿存储空间。

实现步骤

        在拉链表中,每一条数据都有一个生效日期(effective_date)和失效日期(expire_date)。假设在一个用户表中,在2019年11月8日新增了两个用户,如下表所示,则这两条记录的生效时间为当天,由于到2019年11月8日为止,这两条就还没有被修改过,所以失效时间为一个给定的比较大的值,比如:3000-12-31  

member_idphonenocreate_timeupdate_time
10001133000000012019-11-083000-12-31
10002135000000022019-11-083000-12-31

        第二天(2019-11-09),用户10001被删除了,用户10002的电话号码被修改成13600000002.为了保留历史状态,用户10001的失效时间被修改为2019-11-09,用户10002则变成了两条记录,如下表所示: 

member_idphonenocreate_timeupdate_time
10001133000000012019-11-082019-11-09
10002135000000022019-11-082019-11-09
10002136000000022019-11-093000-12-31

        第三天(2019-11-10),又新增了用户10003,则用户表数据如小表所示: 

member_idphonenocreate_timeupdate_time
10001133000000012019-11-082019-11-09
10002135000000022019-11-082019-11-09
10002136000000022019-11-093000-12-31
10003133000000062019-11-103000-12-31

        如果要查询最新的数据,那么只要查询失效时间为3000-12-31的数据即可,如果要查11月8号的历史数据,则筛选生效时间<= 2019-11-08并且失效时间>2019-11-08的数据即可。如果查询11月9号的数据,那么筛选条件则是生效时间<=2019-11-09并且失效时间>2019-11-09

表结构

  • MySQL源member表

CREATE TABLE member(
            member_id VARCHAR ( 64 ),
            phoneno VARCHAR ( 20 ),
            create_time datetime,
            update_time datetime );

  • ODS层增量表member_delta,每天一个分区

CREATE TABLE member_delta
          (member_id string,
            phoneno string,
            create_time string,
            update_time string)
PARTITIONED BY (DAY string);
  • 临时表

CREATE TABLE member_his_tmp
          (member_id string,
            phoneno string,
            effective_date date,
            expire_date date
            );
  • DW层历史拉链表

CREATE TABLE member_his
          (member_id string,
            phoneno string,
            effective_date date,
            expire_date date);

Demo数据准备

2019-11-08的数据为: 

member_idphonenocreate_timeupdate_time
10001135000000012019-11-08 14:47:552019-11-08 14:47:55
10002135000000022019-11-08 14:48:332019-11-08 14:48:33
10003135000000032019-11-08 14:48:532019-11-08 14:48:53
10004135000000042019-11-08 14:49:022019-11-08 14:49:02

2019-11-09的数据为:其中蓝色代表新增数据,红色代表修改的数据

member_idphonenocreate_timeupdate_time
10001135000000012019-11-08 14:47:552019-11-08 14:47:55
10002136000000022019-11-08 14:48:332019-11-09 14:48:33
10003135000000032019-11-08 14:48:532019-11-08 14:48:53
10004135000000042019-11-08 14:49:022019-11-08 14:49:02
10005135000000052019-11-09 08:54:032019-11-09 08:54:03
10006135000000062019-11-09 09:54:252019-11-09 09:54:25

2019-11-10的数据:其中蓝色代表新增数据,红色代表修改的数据  

member_idphonenocreate_timeupdate_time
10001135000000012019-11-08 14:47:552019-11-08 14:47:55
10002136000000022019-11-08 14:48:332019-11-09 14:48:33
10003135000000032019-11-08 14:48:532019-11-08 14:48:53
10004136000000042019-11-08 14:49:022019-11-10 14:49:02
10005135000000052019-11-09 08:54:032019-11-09 08:54:03
10006135000000062019-11-09 09:54:252019-11-09 09:54:25
10007135000000072019-11-10 17:41:492019-11-10 17:41:49

全量初始装载

        在启用拉链表时,先对其进行初始装载,比如以2019-11-08为开始时间,那么将MySQL源表全量抽取到ODS层member_delta表的2018-11-08的分区中,然后初始装载DW层的拉链表member_his

INSERT overwrite TABLE member_his
SELECT
  member_id,
  phoneno,
  to_date ( create_time ) AS effective_date,
 '3000-12-31'
FROM
member_delta
WHERE
DAY = '2019-11-08'

        查询初始的历史拉链表数据

图片

增量抽取数据

        每天,从源系统member表中,将前一天的增量数据抽取到ODS层的增量数据表member_delta对应的分区中。这里的增量需要通过member表中的创建时间和修改时间来确定,或者使用sqoop job监控update时间来进行增联抽取。比如,本案例中2019-11-09和2019-11-10为两个分区,分别存储了2019-11-09和2019-11-10日的增量数据。2019-11-09分区的数据为:

图片

        2019-11-10分区的数据为:

图片

增量刷新历史拉链数据

  • 2019-11-09增量刷新历史拉链表将数据放进临时表

INSERT overwrite TABLE member_his_tmp
SELECT *
FROM
  (
-- 2019-11-09增量数据,代表最新的状态,该数据的生效时间是2019-11-09,过期时间为3000-12-31
-- 这些增量的数据需要被全部加载到历史拉链表中
SELECT member_id,
       phoneno,
       '2019-11-09' effective_date,
                    '3000-12-31' expire_date
   FROM member_delta
   WHERE DAY='2019-11-09'
   UNION ALL 
-- 用当前为生效状态的拉链数据,去left join 增量数据,
-- 如果匹配得上,则表示该数据已发生了更新,
-- 此时,需要将发生更新的数据的过期时间更改为当前时间.
-- 如果匹配不上,则表明该数据没有发生更新,此时过期时间不变
SELECT a.member_id,
       a.phoneno,
       a.effective_date,
       if(b.member_id IS NULL, to_date(a.expire_date), to_date(b.day)) expire_date
   FROM
     (SELECT *
      FROM member_his
      WHERE expire_date='3000-12-31') a
   LEFT JOIN
     (SELECT *
      FROM member_delta
      WHERE DAY='2019-11-09') b ON a.member_id=b.member_id)his

        将数据覆盖到历史拉链表

INSERT overwrite TABLE member_his
SELECT *
FROM member_his_tmp

        查看历史拉链表

图片

  • 2019-11-10增量刷新历史拉链表

                将数据放进临时表

INSERT overwrite TABLE member_his_tmp
SELECT *
FROM
(
-- 2019-11-10增量数据,代表最新的状态,该数据的生效时间是2019-11-10,过期时间为3000-12-31
-- 这些增量的数据需要被全部加载到历史拉链表中
SELECT member_id,
      phoneno,
      '2019-11-10' effective_date,
                   '3000-12-31' expire_date
  FROM member_delta
  WHERE DAY='2019-11-10'
  UNION ALL
-- 用当前为生效状态的拉链数据,去left join 增量数据,
-- 如果匹配得上,则表示该数据已发生了更新,
-- 此时,需要将发生更新的数据的过期时间更改为当前时间.
-- 如果匹配不上,则表明该数据没有发生更新,此时过期时间不变
SELECT a.member_id,
      a.phoneno,
      a.effective_date,
      if(b.member_id IS NULL, to_date(a.expire_date), to_date(b.day)) expire_date
  FROM
    (SELECT *
    FROM member_his
    WHERE expire_date='3000-12-31') a
  LEFT JOIN
    (SELECT *
    FROM member_delta
    WHERE DAY='2019-11-10') b ON a.member_id=b.member_id)his

查看历史拉链表

图片

将以上脚本封装成shell调度的脚本

#!/bin/bash

#如果是输入的日期按照取输入日期;如果没输入日期取当前时间的前一天
if [ -n "$1" ] ;then
    do_date=$1
else
    do_date=`date -d "-1 day" +%F`
fi

sql="

INSERT overwrite TABLE member_his_tmp
SELECT *
FROM
  (
-- 2019-11-10增量数据,代表最新的状态,该数据的生效时间是2019-11-10,过期时间为3000-12-31
-- 这些增量的数据需要被全部加载到历史拉链表中
SELECT member_id,
       phoneno,
       '$do_date' effective_date,
       '3000-12-31' expire_date
   FROM member_delta
   WHERE DAY='$do_date'
   UNION ALL
-- 用当前为生效状态的拉链数据,去left join 增量数据,
-- 如果匹配得上,则表示该数据已发生了更新,
-- 此时,需要将发生更新的数据的过期时间更改为当前时间.
-- 如果匹配不上,则表明该数据没有发生更新,此时过期时间不变
SELECT a.member_id,
       a.phoneno,
       a.effective_date,
       if(b.member_id IS NULL, to_date(a.expire_date), to_date(b.day)) expire_date
   FROM
     (SELECT *
      FROM member_his
      WHERE expire_date='3000-12-31') a
   LEFT JOIN
     (SELECT *
      FROM member_delta
      WHERE DAY='$do_date') b ON a.member_id=b.member_id)his;
"

$hive -e "$sql"

如需获取更多资料,您可以下载知识星球app,并搜索加入‘数据要素X’。


http://www.niftyadmin.cn/n/5740789.html

相关文章

青少年编程与数学 02-003 Go语言网络编程 11课题、Go语言网络编程

青少年编程与数学 02-003 Go语言网络编程 11课题、Go语言网络编程 课题摘要:一、Go语言与网络编程二、Go语言网络编程分类1. 按协议分类2. 按应用层级分类3. 按服务类型分类4. 按并发模型分类5. 按编程范式分类6. 按安全需求分类7. 按性能要求分类8. 按开发框架分类 三、Go语言…

16、论文阅读:Mamba YOLO:用于目标检测的基于 SSM 的 YOLO

Mamba YOLO: SSMs-Based YOLO For Object Detection 总结前言感受野为什么Transformer 的结构被引入&#xff0c;显著扩展了模型的感受野&#xff1f;状态空间模型SSM 介绍相关工作实时目标检测端到端目标检测器视觉状态空间模型 方法预处理整体架构ODSS BlockLocalSpatial Blo…

Rust 跨平台构建与部署实战:构建并部署跨平台应用

第二节&#xff1a;Rust 跨平台构建与部署实战&#xff1a;构建并部署跨平台应用 在这一节中&#xff0c;我们将深入探讨如何利用 Rust 的跨平台构建工具和流程&#xff0c;构建和部署适用于不同平台的应用程序。跨平台开发的核心挑战之一是如何生成能够在多种操作系统和硬件平…

VLAN 高级技术 ——QinQ的配置

QinQ的概述&#xff1a; QinQ技术是一种扩展虚拟局域网&#xff08;VLAN&#xff09;数量空间的技术&#xff0c;通过在802.1Q标签报文的基础上再增加一层802.1Q的Tag来实现。以下是对QinQ技术的详细概述&#xff1a; QinQ技术的定义与背景 定义&#xff1a;QinQ&#xff08…

Kimi出考题,考题提示词Prompt附上,培训机构试题、期中考试、人事入职试题全搞定

大家好&#xff0c;我是Shelly&#xff0c;一个专注于输出AI工具和科技前沿内容的AI应用教练&#xff0c;体验过300款以上的AI应用工具。关注科技及大模型领域对社会的影响10年。关注我一起驾驭AI工具&#xff0c;拥抱AI时代的到来。 AI工具集1&#xff1a;大厂AI工具【共23款…

深入理解感知机:从线性分类到多层感知机的进化【MLP、基础】

1. 感知机模型 感知机&#xff08;Perceptron&#xff09;是一种简单的神经网络模型&#xff0c;主要用于解决 线性可分 的分类问题。它的基本结构如图所示&#xff0c;包括多个输入、权重、阈值和一个激活函数。在感知机的工作过程中&#xff0c;来自每个输入节点 x i x_i x…

多平台编包动态引入依赖的解决方案

最近开发时遇到了这样的需求&#xff0c;A 平台需要引入一个 video.js&#xff0c;B 平台却是不需要的&#xff0c;那么面向 B 平台打包的时候把依赖装进去自然就不大合适。最好的方法是动态引入依赖&#xff0c;根据平台来判断要不要引入 动态引入依赖 很快啊&#xff0c;动…

《MySQL 8 DBA基础教程》第一章习题

1.6 经典习题与面试题 1. 经典习题 &#xff08;1&#xff09;数据库技术发展经历了哪几个阶段? 答案&#xff1a;本小节将为读者介绍数据库技术经历的3个阶段&#xff0c;即层次数据库和网状数据库阶段、关系数据库技术阶段和后关系数据库技术阶段。 1. 层次数据库和网状…