详解数据仓库之拉链表(原理、设计以及在Hive中的实现)

最近发现一本好书,读完感觉讲的非常好,首先安利给大家,国内第一本系统讲解数据血缘的书!点赞!近几天也会安排朋友圈点赞赠书活动(ง•̀_•́)ง

0x00 前言

本文将会谈一谈在数据仓库中拉链表相关的内容,包括它的原理、设计、以及在我们大数据场景下的实现方式。

全文由下面几个部分组成:

  1. 先分享一下拉链表的用途、什么是拉链表。

  2. 通过一些小的使用场景来对拉链表做近一步的阐释,以及拉链表和常用的切片表的区别。

  3. 举一个具体的应用场景,来设计并实现一份拉链表,最后并通过一些例子说明如何使用我们设计的这张表(因为现在Hive的大规模使用,我们会以Hive场景下的设计为例)。

  4. 分析一下拉链表的优缺点,并对前面的提到的一些内容进行补充说明,比如说拉链表和流水表的区别。

0x01 什么是拉链表

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

我们先看一个示例,这就是一张拉链表,存储的是用户的最基本信息以及每条记录的生命周期。我们可以使用这张表拿到最新的当天的最新数据以及之前的历史数据。

图片

我们暂且不对这张表做细致的讲解,后文会专门来阐述怎么来设计、实现和使用它。

拉链表的使用场景

在数据仓库的数据模型设计过程中,经常会遇到下面这种表的设计:

  1. 有一些表的数据量很大,比如一张用户表,大约10亿条记录,50个字段,这种表,即使使用ORC压缩,单张表的存储也会超过100G,在HDFS使用双备份或者三备份的话就更大一些。

  2. 表中的部分字段会被update更新操作,如用户联系方式,产品的描述信息,订单的状态等等。

  3. 需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态。

  4. 表中的记录变化的比例和频率不是很大,比如,总共有10亿的用户,每天新增和发生变化的有200万左右,变化的比例占的很小。

那么对于这种表我该如何设计呢?下面有几种方案可选:

  • 方案一:每天只留最新的一份,比如我们每天用Sqoop抽取最新的一份全量数据到Hive中。

  • 方案二:每天保留一份全量的切片数据。

  • 方案三:使用拉链表。

为什么使用拉链表

现在我们对前面提到的三种进行逐个的分析。

方案一

这种方案就不用多说了,实现起来很简单,每天drop掉前一天的数据,重新抽一份最新的。

优点很明显,节省空间,一些普通的使用也很方便,不用在选择表的时候加一个时间分区什么的。

缺点同样明显,没有历史数据,先翻翻旧账只能通过其它方式,比如从流水表里面抽。

方案二

每天一份全量的切片是一种比较稳妥的方案,而且历史数据也在。

缺点就是存储空间占用量太大太大了,如果对这边表每天都保留一份全量,那么每次全量中会保存很多不变的信息,对存储是极大的浪费,这点我感触还是很深的......

当然我们也可以做一些取舍,比如只保留近一个月的数据?但是,需求是无耻的,数据的生命周期不是我们能完全左右的。

拉链表

拉链表在使用上基本兼顾了我们的需求。

首先它在空间上做了一个取舍,虽说不像方案一那样占用量那么小,但是它每日的增量可能只有方案二的千分之一甚至是万分之一。

其实它能满足方案二所能满足的需求,既能获取最新的数据,也能添加筛选条件也获取历史的数据。

所以我们还是很有必要来使用拉链表的。

0x02 拉链表的设计和实现

如何设计一张拉链表

下面我们来举个栗子详细看一下拉链表。

我们用电商网站的例子,现在以用户的拉链表来说明。

我们先看一下在Mysql关系型数据库里的user表中信息变化。

在2017-01-01这一天表中的数据是:

图片

在2017-01-02这一天表中的数据是, 用户002和004资料进行了修改,005是新增用户:

图片

在2017-01-03这一天表中的数据是, 用户004和005资料进行了修改,006是新增用户:

图片

如果在数据仓库中设计成历史拉链表保存该表,则会有下面这样一张表,这是最新一天(即2017-01-03)的数据:

图片

说明

  • t_start_date表示该条记录的生命周期开始时间,t_end_date表示该条记录的生命周期结束时间。

  • t_end_date = '9999-12-31'表示该条记录目前处于有效状态。

  • 如果查询当前所有有效的记录,则select * from user where t_end_date = '9999-12-31'。

  • 如果查询2017-01-02的历史快照,则select * from user where t_start_date <= '2017-01-02' and t_end_date >= '2017-01-02'。(此处要好好理解,是拉链表比较重要的一块。)

在Hive中实现拉链表

在现在的大数据场景下,大部分的公司都会选择以Hdfs和Hive为主的数据仓库架构。目前的Hdfs版本来讲,其文件系统中的文件是不能做改变的,也就是说Hive的表智能进行删除和添加操作,而不能进行update。基于这个前提,我们来实现拉链表。

还是以上面的用户表为例,我们要实现用户的拉链表。在实现它之前,我们需要先确定一下我们有哪些数据源可以用。

  1. 我们需要一张ODS层的用户全量表。至少需要用它来初始化。

  2. 每日的用户更新表。

而且我们要确定拉链表的时间粒度,比如说拉链表每天只取一个状态,也就是说如果一天有3个状态变更,我们只取最后一个状态,这种天粒度的表其实已经能解决大部分的问题了。

另外,补充一下每日的用户更新表该怎么获取,据笔者的经验,有3种方式拿到或者间接拿到每日的用户增量,因为它比较重要,所以详细说明:

  1. 我们可以监听Mysql数据的变化,比如说用Canal,最后合并每日的变化,获取到最后的一个状态。

  2. 假设我们每天都会获得一份切片数据,我们可以通过取两天切片数据的不同来作为每日更新表,这种情况下我们可以对所有的字段先进行concat,再取md5,这样就ok了。

  3. 流水表!有每日的变更流水表。

ods层的user表

现在我们来看一下我们ods层的用户资料切片表的结构:

CREATE EXTERNAL TABLE ods.user (user_num STRING COMMENT '用户编号',mobile STRING COMMENT '手机号码',reg_date STRING COMMENT '注册日期'
COMMENT '用户资料表'
PARTITIONED BY (dt string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
STORED AS ORC
LOCATION '/ods/user';
)

ods层的user_update表

然后我们还需要一张用户每日更新表,前面已经分析过该如果得到这张表,现在我们假设它已经存在。

CREATE EXTERNAL TABLE ods.user_update (user_num STRING COMMENT '用户编号',mobile STRING COMMENT '手机号码',reg_date STRING COMMENT '注册日期'
COMMENT '每日用户资料更新表'
PARTITIONED BY (dt string)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
STORED AS ORC
LOCATION '/ods/user_update';
)

拉链表

现在我们创建一张拉链表:

CREATE EXTERNAL TABLE dws.user_his (user_num STRING COMMENT '用户编号',mobile STRING COMMENT '手机号码',reg_date STRING COMMENT '用户编号',t_start_date ,t_end_date
COMMENT '用户资料拉链表'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
STORED AS ORC
LOCATION '/dws/user_his';
)

实现sql语句

然后初始化的sql就不写了,其实就相当于是拿一天的ods层用户表过来就行,我们写一下每日的更新语句。

现在我们假设我们已经已经初始化了2017-01-01的日期,然后需要更新2017-01-02那一天的数据,我们有了下面的Sql。

然后把两个日期设置为变量就可以了。

INSERT OVERWRITE TABLE dws.user_his
SELECT * FROM
(SELECT A.user_num,A.mobile,A.reg_date,A.t_start_time,CASEWHEN A.t_end_time = '9999-12-31' AND B.user_num IS NOT NULL THEN '2017-01-01'ELSE A.t_end_timeEND AS t_end_timeFROM dws.user_his AS ALEFT JOIN ods.user_update AS BON A.user_num = B.user_num
UNIONSELECT C.user_num,C.mobile,C.reg_date,'2017-01-02' AS t_start_time,'9999-12-31' AS t_end_timeFROM ods.user_update AS C
) AS T

0x03 补充

好了,我们分析了拉链表的原理、设计思路、并且在Hive环境下实现了一份拉链表,下面对拉链表做一些小的补充。

拉链表和流水表

流水表存放的是一个用户的变更记录,比如在一张流水表中,一天的数据中,会存放一个用户的每条修改记录,但是在拉链表中只有一条记录。

这是拉链表设计时需要注意的一个粒度问题。我们当然也可以设置的粒度更小一些,一般按

天就足够。

查询性能

拉链表当然也会遇到查询性能的问题,比如说我们存放了5年的拉链数据,那么这张表势必会比较大,当查询的时候性能就比较低了,个人认为两个思路来解决:

  1. 在一些查询引擎中,我们对start_date和end_date做索引,这样能提高不少性能。

  2. 保留部分历史数据,比如说我们一张表里面存放全量的拉链表数据,然后再对外暴露一张只提供近3个月数据的拉链表。

0xFF 总结

我们在这篇文章里面详细地分享了一下和拉链表相关的知识点,但是仍然会有一会遗漏。欢迎交流。

在后面的使用中又有了一些心得,补充进来:

  1. 使用拉链表的时候可以不加t_end_date,即失效日期,但是加上之后,能优化很多查询。

  2. 可以加上当前行状态标识,能快速定位到当前状态。

  3. 在拉链表的设计中可以加一些内容,因为我们每天保存一个状态,如果我们在这个状态里面加一个字段,比如如当天修改次数,那么拉链表的作用就会更大。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ZYNQ_project:key_beep

通过按键控制蜂鸣器工作。 模块框图&#xff1a; 时序图&#xff1a; 代码&#xff1a; /*1位按键消抖 */ module key_filter (input wire sys_clk ,input wire sys_rst_n ,input wire key_in ,output …

springboot项目使用Swagger3

一、Swagger介绍 号称世界上最流行的Api框架&#xff1b;Restful Api 文档在线自动生成工具>Api文档与API定义同步更新直接运行&#xff0c;可以在在线测试API 接口支持多种语言&#xff1a;&#xff08;java&#xff0c;Php…&#xff09; 二、Swagger3 准备工作 1、在p…

VsCode 安装 GitHub Copilot插件 (最新)

##在线安装&#xff1a; 打开Vscode扩展商店&#xff0c;输入 "GitHub Copilot " ,选择下载人数最多的那个。&#xff08;这个是你写一部分代码或者注释&#xff0c;Ai自动帮你提示/补全代码&#xff09;,建议选择这个 注意下面有个和他类似的 "GitHub Copilo…

BMVC 23丨多模态CLIP:用于3D场景问答任务的对比视觉语言预训练

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2306.02329 摘要&#xff1a; 训练模型将常识性语言知识和视觉概念从 2D 图像应用到 3D 场景理解是研究人员最近才开始探索的一个有前景的方向。然而&#xff0c…

APS、SAP解析BOM批量核对(我的APS项目三)

APS提供了解析BOM接口 SAP从CU50中解析了BOM 博主开发了一个程序&#xff0c;把两边的BOM数据拉到一起来比对&#xff0c;从最初的一个车型&#xff0c;增加到5个车型&#xff0c;最后成型是30个车型&#xff0c;几乎覆盖了F1、F2的全部车型。 并且程序还实现了消息提醒功能&…

Kotlin(十) 空指针检查、字符串内嵌表达式以及函数默认值

空指针检查 我们在之前的章节里&#xff0c;有定义一个Study的类&#xff0c;它有两个函数&#xff0c;一个doHomework(),一个readBooks()。然后我们定义个doStudy函数&#xff0c;来调用它们&#xff0c;代码如下&#xff1a; fun doStudy(study: Study) {study.doHomework(…

直播间自动发言机器人的运行分享,与开发需要到的技术分析

先来看实操成果&#xff0c;↑↑需要的同学可看我名字↖↖↖↖↖&#xff0c;或评论888无偿分享 一、引言 随着人工智能技术的不断发展&#xff0c;自动发言机器人已经成为了当今社交媒体领域的重要组成部分。它们能够自动化地发布内容、回复用户评论和消息&#xff0c;大大提高…

RE切入点:选择SLI,设定SLO

还是先来复习下上节课讲的“系统可用性”的两种计算方式&#xff0c;一种是从故障角度出发&#xff0c;以时长维度对系统进行稳定性评估&#xff1b;另一种是从成功请求占比角度出发&#xff0c;以请求维度对系统进行稳定性评估。同时&#xff0c;我们还讲到&#xff0c;在 SRE…

Django中简单的增删改查

用户列表展示 建立列表 views.py def userlist(request):return render(request,userlist.html) urls.py urlpatterns [path(admin/, admin.site.urls),path(userlist/, views.userlist), ]templates----userlist.html <!DOCTYPE html> <html lang"en">…

【开源项目】snakeflow流程引擎研究

项目地址 https://gitee.com/yuqs/snakerflow https://toscode.mulanos.cn/zc-libre/snakerflow-spring-boot-stater &#xff08;推荐&#xff09; https://github.com/snakerflow-starter/snakerflow-spring-boot-starter 常用API 部署流程 processId engine.process().de…

Adversarial Training Methods for Deep Learning: A Systematic Review

Adversarial Training Methods for Deep Learning: A Systematic Review----《面向深度学习的对抗训练方法:系统回顾》 摘要 通过快速梯度符号法(FGSM)、投影梯度下降法(PGD)和其他攻击算法&#xff0c;深度神经网络暴露在对抗攻击的风险下。对抗性训练是用来防御对抗性攻击威…

CoRL 2023 获奖论文公布,manipulation、强化学习等主题成热门

今年大模型及具身智能领域有了非常多的突破性进展&#xff0c;作为机器人学与机器学习交叉领域的全球顶级学术会议之一&#xff0c;CoRL也得到了更多的关注。 CoRL 是面向机器人学习的顶会&#xff0c;涵盖机器人学、机器学习和控制等多个主题&#xff0c;包括理论与应用。今年…

USB拦截工具

USB 闪存驱动器对组织的安全和数据构成了独特的威胁。它们的便携性和充足的存储容量使它们成为数据盗窃的便捷媒介。 什么是 USB 拦截器 USB&#xff08;通用串行总线&#xff09;阻止程序用于禁用插入可移动存储设备的端口&#xff0c;便携性和充足的存储容量使 USB 成为可能…

一文了解芯片测试项目和检测方法 -纳米软件

芯片检测是芯片设计、生产、制造成过程中的关键环节&#xff0c;检测芯片的质量、性能、功能等&#xff0c;以满足设计要求和市场需求&#xff0c;确保芯片可以长期稳定运行。芯片测试内容众多&#xff0c;检测方法多样&#xff0c;今天纳米软件将为您介绍芯片的检测项目都有哪…

电脑小Tip---外接键盘F1-F12快捷键与笔记本不同步

当笔记本外接一款非常好用的静音键盘后&#xff0c;会出现一些问题。例如&#xff1a;外接键盘F1-F12与笔记本不同步。具体一个例子就是&#xff0c;在运行matlab程序时&#xff0c;需要点编辑器—运行&#xff0c;这样就很麻烦&#xff0c;直接运行的快捷键是笔记本键盘上的F5…

macOS文本编辑器 BBEdit 最新 for mac

BBEdit是一款功能强大的文本编辑器&#xff0c;适用于Mac操作系统。它由Bare Bones Software开发&#xff0c;旨在为开发者和写作人员提供专业级的文本编辑工具。 以下是BBEdit的一些主要特点和功能&#xff1a; 多语言支持&#xff1a;BBEdit支持多种编程语言和标记语言&…

[WSL] 安装hive3.1.2成功后, 使用datagrip连接失败

org.apache.hadoop.ipc.RemoteException:User: xxx is not allowed to impersonate anonymous 下载driver-hive-jdbc-3.1.2-standalone 解决 修改hadoop 配置文件 etc/hadoop/core-site.xml,加入如下配置项 <property><name>hadoop.proxyuser.你的用户名.hosts…

机器学习算法实战实战案例代码详解

文章目录 1.问题建模数据预处理 结果分析数据探索特征工程特征选择模型融合 1.问题建模 导入库 import numpy as np import pandas as pd from sklearn.model_selection import KFold from sklearn.metrics import mean_squared_error from sklearn.preprocessing import One…

【Linux】八、进程通信

进程通信的介绍 目的 数据传输&#xff1a;一个进程将它的数据发送给另一个进程&#xff1b; 资源共享&#xff1a;多个进程间共享资源&#xff1b; 通知事件&#xff1a;一个进程向另一个或一组进程发送消息&#xff0c;同时事件如&#xff0c;进程终止时要通知父进程&#xf…