hive中实现行转列_漫谈数据仓库之拉链表(原理、设计以及在Hive中的实现)

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

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

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

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

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

0x01 什么是拉链表

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

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

56569d96f1b44fe0e0c7e0e694cda057.png

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

拉链表的使用场景

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

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

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

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

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

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

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

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

方案三:使用拉链表。

为什么使用拉链表

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

方案一

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

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

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

方案二

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

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

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

拉链表

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

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

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

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

0x02 拉链表的设计和实现

如何设计一张拉链表

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

我们接上在《漫谈数据仓库之维度建模》中的电商网站的例子,现在以用户的拉链表来说明。

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

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

2160415c94e036716e7285dbb18ea7a9.png

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

a9d19398d0520956a8108dc43c0d76e6.png

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

3f09d6d62cc3daee00c6c4ea9e7bb0be.png

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

14d3e40ab7b791e60bbe595174244335.png

说明

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。基于这个前提,我们来实现拉链表。

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

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

每日的用户更新表。

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

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

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

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

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

ods层的user表

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

5083c7bb723f9c671889ccf5b515e486.png

ods层的user_update表

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

442ed099047eada9c708aeb8834b321b.png

拉链表

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

12dc6c8d55a3a14a088480c19e0364f6.png

实现sql语句

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

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

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

832e9fd778aa0f5707240e5558ea9b54.png

0x03 补充

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

拉链表和流水表

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

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

查询性能

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

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

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

0xFF 总结

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

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

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

相关文章

算法导论:堆排序

堆 堆是一个数组&#xff0c;它可以被看成一个近似的完全二叉树&#xff0c;树上的每一个结点对应数组中的一个元素。除去最底层外&#xff0c;该树是完全充满的&#xff0c;而且从左到右填充。 用数组A表示堆&#xff0c;从数组第1个元素开始&#xff0c;数组中第i&#xff08…

扩展坞可以把手机投到显示器吗_解锁4K 60Hz毕亚兹USB Type-C扩展坞体验

现在很多白领办公、学生上网课都会使用到笔记本电脑&#xff0c;尤其是近两年的轻薄本&#xff0c;为了追求轻量化&#xff0c;砍掉了原本很多的接口&#xff0c;转而使用Type-C来代替&#xff0c;从而导致接驳外设的时候非常不方便。特别是那种只给了一个USB标准接口的电脑&am…

Android view.settran,Android RecyclerView从入门到玩坏

目录前言基础使用分隔线点击监听搭配CardView更丰富的条目增删条目快速添加视图让RecyclerView支持复杂视图最后前言RecyclerView在Android界面开发当中是很重要的, 那掌握它也是很必要的. 但是有些时候会觉得它很厚重, 这里就从RecyclerView的基础一直说到扩展, 让你把Recycle…

python提取英文单词 每行显示一个_使用python对文件中的单词进行提取

由于需要使用一个纯单词组成的文件&#xff0c;在网上下载到了一个存放单词的文件&#xff0c;但是里面有中文的解释&#xff0c;那就需要做一下提取了。 文本的形式如下&#xff1a;所见即所得&#xff0c;这个文本是有规律的&#xff0c;每个单词为一行&#xff0c;紧接着下一…

微服务feignclient_搞微服务用阿里开源的 Nacos 真香啊

本文适合有 Java 基础知识的人群本文作者&#xff1a;HelloGitHub-秦人HelloGitHub 推出的《讲解开源项目》系列&#xff0c;今天给大家带来一款开源 Java 版可以实现动态服务发现&#xff0c;配置和服务管理平台——Nacos&#xff0c;它是阿里巴巴团队推出的&#xff0c;符合国…

华为mate40搭载鸿蒙,华为mate40搭载鸿蒙还是EMUI11,答案来了

原标题&#xff1a;华为mate40搭载鸿蒙还是EMUI11&#xff0c;答案来了今年秋季苹果要发布首款5G版iPhone手机iPhone12&#xff0c;搭载A14处理器首发iOS14系统。而华为也要发布新款旗舰手机华为mate40系列手机&#xff0c;搭载华为麒麟1020处理器&#xff0c;首发EMUI11系统。…

称重管理系统如何修改重量_无人值守称重系统硬件配置和作用

1. 视频监控抓拍系统软件配合设摄像头在保存数据的同时抓拍&#xff0c;防止车辆或者人为的舞弊行为2. 红外定位在地磅否的两侧各安装一对红外对射&#xff0c;通过信号线连接到开关&#xff0c;当红外的光束被阻挡时&#xff0c;红外定位系统将自动发出警告&#xff0c;禁止称…

在建工程直接费用化_威县垃圾发电在建项目被罚后续:现已整改

新京报讯(记者 李大伟)3月11日&#xff0c;针对此前因环保问题被处罚一事&#xff0c;威县垃圾发电在建项目(下称威县项目)的项目方宁夏电力建设工程公司相关负责人罗中辉表示&#xff1a;目前&#xff0c;该项目已整改完成。“所有道路上的浮土已彻底清扫&#xff0c;所有的裸…

centos 断电重启后,文件系统损坏修复

为什么80%的码农都做不了架构师&#xff1f;>>> centos 断电重启后&#xff0c;由于文件系统损坏&#xff0c;无法正常开机&#xff0c;常常出现“an error occurred during the file system check” 提示&#xff0c;就是说系统文件损坏啦&#xff0c;这时候要用f…

如何对聚类结果进行分析_如何更合理地给聚类结果贴标签——由一个挖掘学生用户的项目说开去...

”聚类一时爽&#xff0c;判断两行泪“——这是解决任何一个无监督问题时都会面临的苦恼&#xff1a;最近接到了一个无监督问题的项目——给一群无标签的结构化数据贴标签&#xff0c;随后我便立即展开了工作&#xff0c;首先开始查阅资料&#xff0c;然后把EDA(数据探索) 、特…

查看文件二进制编码_小白也能学会系列:用python文件读写代码实例!(简单案例)...

前言&#xff1a;不久之前&#xff0c;从一个.dat文件中读取波形数据&#xff0c;通过一个自编码网络进行异常检测。所以特意在此写出来&#xff0c;咱从最基础的文件读写开始吧。先说数据&#xff0c;是一个int16型的数组。说是数组&#xff0c;但是读取也并不简单。众所周知&…

stm32 ucosii消息队列 串口_STM32F1的UART4串口配置

注意是UART4&#xff0c;不是USART4在stm32中UART和USART是不相同的USART是通用同步/异步串行接收/发送器UART是通用异步收发传输器简单区分同步和异步就是看通信时需不需要对外提供时钟输出&#xff0c;我们平时用的串口通信基本都是 UART。USART支持同步模式&#xff0c;因此…

程序员微信头像_微信头像暴露了你的层次:层次越低的人,越喜欢用这些头像...

这个话题&#xff0c;原本很轻松。但往细里看&#xff0c;它背后玄机很多。许多未知理论与认知可能性&#xff0c;往往就在不为人知的拐角处。卞之琳有一首诗&#xff1a;你站在桥上看风景&#xff0c;看风景的人在楼上看你。明月装饰了你的窗子&#xff0c;你装饰了别人的梦。…

华为鸿蒙系统正式拜拜,从“哄蒙”到“鸿蒙”,现在,正式对华为鸿蒙OS说你好!...

从鸿蒙发布之初一直到现在&#xff0c;很多网友都为鸿蒙出谋划策&#xff0c;毕竟是我们自己的系统&#xff0c;而现在也确实需要一套自研的、成熟的智能操作系统了。再加上鸿蒙万物互联的这个大设想&#xff0c;大家伙确实是很兴奋&#xff0c;同时在这个时代里面&#xff0c;…

英文书《用unreal来学习c++》_用机器学习来概括《哈利波特》,四句话总结一场戏...

毒栗子 发自 凹非寺量子位 出品 | 公众号 QbitAI文章太长读不下去的时候&#xff0c;就想有个TL;DR按钮&#xff0c;用最短的时间&#xff0c;看最关键的部分。要是视频很长不想看&#xff0c;该怎么挑重点食用&#xff1f;一位叫做Sagi Shaier的程序猿&#xff0c;用机器学习给…

什么是负边沿触发_用好示波器必须学会的知识:触发方式

我们先简单回顾下什么是示波器的触发。由于信号无时无刻都在变化&#xff0c;如果一股脑的都把他们显示在示波器上&#xff0c;就会很乱&#xff0c;根本无法让我们看清楚&#xff0c;从而也就无法观察信号来解决问题。考虑到信号大多数时候都是以某种规律周期性出现的&#xf…

html placehonlder属性,HTML input placeholder 属性

HTML placeholder 属性实例 1带有 placeholder 文本的两个输入字段&#xff1a;尝试一下 placeholder 文本也可以指定颜色。实例 2带有 placeholder 文本设置颜色&#xff1a;尝试一下 浏览器支持Internet Explorer 10、Firefox、Opera、Chrome 和 Safari 支持 placeholder 属性…

python画图显示不了中文_完美解决Python matplotlib绘图时汉字显示不正常的问题

Matplotlib是一个很好的作图软件&#xff0c;但是python下默认不支持中文&#xff0c;所以需要做一些修改&#xff0c;方法如下&#xff1a; 1.在python安装目录的Lib目录下创建ch.py文件。 文件中代码为&#xff1a; 保存&#xff0c;以后通过以下代码调用&#xff1a; #-*-co…

监听一个可下拉区域的滚动监听_Flutter 实现一个悬浮的效果

知乎视频​www.zhihu.com在原来的基础布局下修改江景&#xff1a;Flutter 实现钉钉侧边栏​zhuanlan.zhihu.com修改 DTMessageScreen使用 Stack 作为容器且套 SingleChildScrollView &#xff0c;监听 controller 滚动事件再 Stack 容器中多添加一个DTMessageTopQuick&#xff…

【Hive】——函数案例

1 Hive 多字节分隔符处理 1.1 默认规则 Hive默认序列化类是LazySimpleSerDe&#xff0c;其只支持使用单字节分隔符&#xff08;char&#xff09;来加载文本数据&#xff0c;例如逗号、制表符、空格等等&#xff0c;默认的分隔符为”\001”。根据不同文件的不同分隔符&#xf…