【大数据hive】hive 拉链表设计与实现

news2024/11/29 11:50:12

目录

一、前言

二、拉链表业务背景

2.1 数据同步引发的问题

2.1.1 解决方案1

2.1.2 解决方案2

2.1.3 解决方案3

三、拉链表设计与原理

3.1 功能与应用场景

3.2 实现步骤

3.2.1 Step1

3.2.2  Step2

3.2.3 Step3

3.3 操作演示

3.3.1 创建一张表并加载数据

3.3.2 模拟增量数据变化

3.3.3 合并数据


一、前言

做过电商开发的同学对订单的业务应该不陌生,比如对一条订单数据来说,通常会有一个类似于status的字段来标识这个订单的完整的生命周期,从存储的数据来看,一张表只需要存储这一条数据即可。

但是对于数据分析来看,为了跟踪这个订单的全生命周期的完整过程来说,这并不是一个很好的设计,假如说订单到已支付但未发货,而且在未发货这一步停留的时间很长,对于大数据分析场景来说,这就是一个重要的分析场景,但对于mysql存储的订单表来说,这就有些冗余了。这也就是说,mysql在设计表的时候,是会充分考虑冗余数据量带来的性能问题。

二、拉链表业务背景

我们知道,Hive在实际工作中主要用于构建离线数据仓库,定期的从各种数据源中同步采集数据到Hive中,经过分层转换提供数据给上层其他应用使用。

例如:有一个定时任务每天从MySQL中同步最新的订单信息、用户信息、店铺信息等到数据仓库中,从而进行订单分析、用户分析等。

如下图所示,为一个数仓简单的业务流程图;

2.1 数据同步引发的问题

有下面这样一张用户表tb_user,有过开发经验的同学对类似的订单表应该不陌生,比如每次注册完一个用户后,该表中就会产生一条新的数据,记录了该用户的id、手机号码、用户名、性别、地址等信息。

关于该表在业务中的具体使用场景如下:

  • 每天都会有用户注册,产生新的用户信息;
  • 每天都需要将MySQL中的用户数据同步到Hive数据仓库中;
  • 需要对用户的信息做统计分析,例如统计新增用户的个数、用户性别分布、地区分布、运营商分布等指标;

数据同步的过程大概长下面这样

 比如说,在2021-01-01这一天,MySQL中有10条用户信息;

然后通过中间程序(或其他方式)同步到下面的Hive表中了;

现在,假如在 2021-01-02 这一天,在前一天的基础上,MySQL中新增了2条用户注册数据,并且其中有1条用户数据发生更新,

  • 新增两条用户数据011和012;
  • 008的addr发生了更新,从gz更新为sh;

到了2021-01-03这天,Hive需要对2号的数据进行同步更新处理,此时问题来了:

新增的数据会直接加载到Hive表中,但是更新的数据如何存储在Hive表中?

2.1.1 解决方案1

在Hive中用新的addr覆盖008的老的addr,直接更新

 这么做的优点是:实现最简单,使用起来最方便,但缺点也是很明显的,没有历史状态,008的地址是1月2号在sh,但是1月2号之前是在gz的,如果要查询008的1月2号之前的addr就无法查询,也不能使用sh代替;

2.1.2 解决方案2

每次数据改变,根据日期构建一份全量的快照表,每天一张表

这样做的优点是:记录了所有数据在不同时间的状态, 缺点:冗余存储了很多没有发生变化的数据,导致存储的数据量过大;

2.1.3 解决方案3

构建拉链表,通过时间标记发生变化的数据的每种状态的时间周期,如下图表中数据所示,它大意就是,当一条数据中的关键业务标识字段发送了变化,将新增加一条数据,将这条数据的过期时间设置的非常大,作为这条数据的边界,同样主键的数据再次过来的时候,在新增的一条记录中只需要记录变化的字段即可;关于拉链表,下文将做详细的讲述;

三、拉链表设计与原理

3.1 功能与应用场景

拉链表专门用于解决在数据仓库中数据发生变化如何实现数据存储的问题。

拉链表的设计是将更新的数据进行状态记录,没有发生更新的数据不进行状态存储,用于存储所有数据在不同时间上的所有状态,通过时间进行标记每个状态的生命周期,查询时,根据需求可以获取指定时间范围状态的数据,默认用9999-12-31等最大值来表示最新状态。

如下图所示,记录了某些订单的完整生命周期;

3.2 实现步骤

用下面这张图来说明其完整的实现过程

具体来说,操作步骤如下:

3.2.1 Step1

增量采集变化数据,放入增量表中。

3.2.2  Step2

将Hive中的拉链表与临时表的数据进行合并,合并结果写入临时表。

3.2.3 Step3

将临时表的数据覆盖写入拉链表中。

3.3 操作演示

准备一份原始数据,内容如下

3.3.1 创建一张表并加载数据

--创建拉链表
create table dw_zipper(
                          userid string,
                          phone string,
                          nick string,
                          gender int,
                          addr string,
                          starttime string,
                          endtime string
) row format delimited fields terminated by '\t';

--加载模拟数据
load data local inpath '/usr/local/soft/selectdata/zipper.txt' into table dw_zipper;

执行过程

 检查数据是否加载进去

3.3.2 模拟增量数据变化

下面为两条新增的数据,以及一条变化的数据

创建一张增量表,并加载数据

create table ods_zipper_update(
                                  userid string,
                                  phone string,
                                  nick string,
                                  gender int,
                                  addr string,
                                  starttime string,
                                  endtime string
) row format delimited fields terminated by '\t';

load data local inpath '/usr/local/soft/selectdata/update.txt' into table ods_zipper_update;

 执行过程

检查数据是否加载成功

 

3.3.3 合并数据

创建一张临时表

create table tmp_zipper(
                           userid string,
                           phone string,
                           nick string,
                           gender int,
                           addr string,
                           starttime string,
                           endtime string
) row format delimited fields terminated by '\t';

执行过程

合并拉链表与增量表

insert overwrite table tmp_zipper
select
    userid,
    phone,
    nick,
    gender,
    addr,
    starttime,
    endtime
from ods_zipper_update
union all
--查询原来拉链表的所有数据,并将这次需要更新的数据的endTime更改为更新值的startTime
select
    a.userid,
    a.phone,
    a.nick,
    a.gender,
    a.addr,
    a.starttime,
    --如果这条数据没有更新或者这条数据不是要更改的数据,就保留原来的值,否则就改为新数据的开始时间-1
    if(b.userid is null or a.endtime < '9999-12-31', a.endtime , date_sub(b.starttime,1)) as endtime
from dw_zipper a  left join ods_zipper_update b
                            on a.userid = b.userid ;

执行上面的sql

覆盖拉链表

insert overwrite table dw_zipper
select * from tmp_zipper;

执行过程

执行完成后,检查拉链表的数据,可以看到新增了2条数据,同时对于相同的那条数据做了时间上的更新;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/663973.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高级数据分析师工作的基本职责(合集)

高级数据分析师工作的基本职责1 职责&#xff1a; 1. 负责出行平台层面司乘用户分析&#xff0c;给平台相关业务及策略建设输入洞察和方法; 2. 形成天、周和月度的分析报告&#xff0c;传递给公司管理层并进行定期汇报; 3. 可独立完成针对特定问题的分析解读&#xff0c;支持临…

【数据分享】2023年全国范围的1km分辨率高新技术企业数量栅格数据

企业是经济活动的参与主体。一个城市的企业数量决定了这个城市的经济发展水平&#xff01;比如一个城市的金融企业较多&#xff0c;那这个城市的金融产业肯定比较发达&#xff1b;一个城市的制造业企业较多&#xff0c;那这个城市的制造业肯定比较发达。 目前&#xff0c;在城…

插件 - 一份配置,离插件机制只有一步之遥

文章目录 Pre优化方案流程图优点缺点举例论证CodePre 插件 - 通过SPI方式实现插件管理 中我们提到了缺点 无法保证唯一实现:在SPI机制中,同一个服务接口可能会有多个提供者实现,而无法明确指定使用哪一个。依赖于配置文件:配置文件是发现和加载提供者的关键,如果配置文件…

Java泛型中的T、E、K、V、?通配符,你确定都了解吗?

目录 前言 泛型带来的好处 泛型中通配符 小结 前言 Java 泛型&#xff08;generics&#xff09;是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制&#xff0c;该机制允许开发者在编译时检测到非法的类型。 泛型的本质是参数化类型&#xff0c;也就是说所操…

7.controller部署neutron服务

Neutron 为整个 openstack 提供虚拟化的网络支持&#xff0c;主要功能包括二层交换、三层路由、防火墙、VPN &#xff0c;以及负载均衡等。 neutron数据库配置 controller节点 在安装和配置 neutron 服务之前&#xff0c;必须创建服务对应的数据库用于存储相关数据 &#xff0…

多模态简介

1. 多模态定义 多模式深度学习是一个机器学习子领域&#xff0c;旨在训练人工智能模型来处理和发现不同类型数据&#xff08;模式&#xff09;之间的关系——通常是图像、视频、音频和文本。通过结合不同的模态&#xff0c;深度学习模型可以更普遍地理解其环境&#xff0c;因为…

【C++】I/O流类库

I/O 数据的输入和输出&#xff08;input/output简写为I/O&#xff09;&#xff0c;对标准输入设备和标准输出设备的输入输出简称为标准I/O。对在外存磁盘上的文件输入输出简称为文件I/O。对内存中指定的字符串存储空间的输入输出简称为串I/O。 流 数据输入输出的过程&#x…

边缘智能:边缘计算和人工智能的深度融合

摘要 随着通信技术的飞速发展和移动设备使用的激增&#xff0c;一种全新的计算范式——边缘计算正在迅速普及。与此同时&#xff0c;随着深度学习的突破和硬件架构的许多改进&#xff0c;人工智能(AI)应用正在蓬勃发展。在网络边缘产生数十亿字节的数据&#xff0c;对数据处理…

也聊聊BLDC 电机的 10 大热门应用---【其利天下技术分享】

近年来&#xff0c;随着全球提出的低碳&#xff0c;高能效的概念提出&#xff0c;作为高效动力来源的BLDC技术&#xff0c;越来越受到各界的追捧。 大家都知道&#xff0c;BLDC的发展史也就短短几十年的时间&#xff0c;随着近年来&#xff0c;新磁性材料的运用、微电子技术和…

基于大模型的虚拟数字人__虚拟主播实例

基于大模型的虚拟数字人__虚拟主播实例 本文目录&#xff1a; 一、技术的背景&#xff1a; 二、创意名称&#xff1a; 三、创意背景 四、创意目标 五、创意设计 六、技术实现路径 七、完整代码实现 八、创意总结 九、人工智能虚拟人物的一些优秀代表作品及其特点 十、…

河道水位标尺识别预警 yolov7

河道水位标尺识别预警系统通过pythonyolov7网络模型技术&#xff0c;河道水位标尺识别预警算法对河道水位标尺进行实时监测&#xff0c;当河道水位出现异常情况时&#xff0c;河道水位标尺识别预警算法将自动发出警报提示后台管理人员及时采取措施。YOLO系列算法是一类典型的on…

【工具篇】SpringBoot基于assembly的服务化打包方案

简介 最近项目中&#xff0c;使用插件式开发方式&#xff0c;将多个Web应用打成一个FatJar程序包部署运行。但考虑到原始裸Jar包方式交付&#xff0c;有很多不便之处&#xff0c;比如启动命令过长&#xff08;JVM参数配置、Spring环境配置等&#xff09;、配置无法修改等问题会…

基于OpenMV的自动驾驶智能小车模拟系统

一、项目简介 基于机器视觉模块OpenMV采集车道、红绿灯、交通标志等模拟路况信息&#xff0c;实现一辆能车道保持、红绿灯识别、交通标志识别、安全避障以及远程WiFi控制的多功能无人驾驶小车。 赛道规格&#xff1a; 1、编程所需软件&#xff1a; OpenMV&#xff1a;使用Op…

cuda pyinstall cvs 使用记录

1.pip 换源 pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/2.安装匹配cuda的pytorch 官网&#xff1a;PyTorch pip3 install torch torchvision torchaudio查看能否使用cuda: import torch torch.cuda.is_available()获得以下反馈&#xff1a; 意思…

CSS基础学习--22 图像透明/不透明

一、透明度属性 CSS3中属性的透明度是 opacity 正常的图像 相同的图像带有透明度&#xff1a; img {opacity:0.4;filter:alpha(opacity40); /* IE8 及其更早版本 */ } 备注&#xff1a;Opacity属性值从0.0 - 1.0。值越小&#xff0c;使得元素更加透明。 IE8和早期版本使用滤…

【MySQL】库和表结构的增删查改

目录 一、库的操作 1、创建数据库 2、数据库所使用的编码 2.1查询编码集和校验集 2.2查看数据库的字符集和校验集 2.3创建数据库指定字符集和校验集 2.4不同的校验集所筛选的数据结果不一样 3、查看数据库 4、修改数据库 5、删除数据库 6、数据库的备份和恢复 6.1备…

【Spring MVC】获取 @RequsetBody 标识的对象,使用适配器模式增加代码可读性

1. 前言 一个技术需求引发的思考和实践&#xff1a; 思考 用 AOP 把校验代码 实践 用 Spring MVC 的 RequestBodyAdvice 做AOP逻辑继承 RequestBodyAdviceAdapter 实现自己的 适配器用自己的适配器让代码可读性增加熟悉 Spring MVC 、Java 反射的一些实践 本文内容 澄清一个A…

Mysql 调优

前言 硬件层面&#xff1a;使用固态硬盘、扩大内存、加大带宽等等 架构层面&#xff1a;主从复制实现读写分离【一主一 或 双主双从】 表结构层面&#xff1a;对表结构进行垂直拆分、水平分表、分库分表。常用的数据库中间件有&#xff1a;MySQL Proxy、MyCat以及ShardingSphe…

电脑C盘的清理 | 微信QQ缓存信息

记录一下我处理C盘爆满时的几个方法&#xff0c;基本上都是可以日常使用的。 一、磁盘清理 链接 二、查看具体哪些文件占内存 win图标右击 -----> 点击“系统&#xff08;Y&#xff09;” 点击查看具体是哪些文件夹哪些app占用了大量的内存&#xff0c;并选择删除部分…

第二章 re模块

1. re模块介绍 正则表达式 在处理字符串时&#xff0c;经常会有查找符合某些复杂规则的字符串的需求。正则表达式就是用于描述这些规则的工具。换句话说&#xff0c;正则表达式就是记录文本规则的代码。 re 模块 Python 提供了 re 模块用于实现正则表达式的操作。在实现时&…