数据仓库-拉链表

在数据仓库中制作拉链表,可以按照以下步骤进行:

  1. 确定需求:首先明确需要使用拉链表的场景和需求。例如,可能需要记录历史数据的变化,以便进行时间序列分析等。
  2. 设计表结构:在数据仓库中,拉链表通常由两个表组成:当前表和历史表。当前表存储最新的数据,历史表存储过去的数据。两个表的结构应该相同,包含相同的字段。
  3. 建立当前表:创建一个当前表,用于存储最新的数据。该表应包含需要记录的所有字段,以及一个表示有效期的字段。有效期字段用于标识该条数据在何时失效。
  4. 建立历史表:创建一个历史表,用于存储过去的数据。该表的结构与当前表相同,但还应包含一个表示生效日期的字段。生效日期字段用于标识该条数据在何时生效。
  5. 数据插入与更新:当有新数据插入时,将其插入到当前表中,并设置相应的有效期。同时,将过期的数据从当前表中移动到历史表中,并更新它们的生效日期和有效期。
  6. 数据查询:在查询数据时,同时查询当前表和历史表。根据查询的时间范围,确定在哪个表中查找数据。
  7. 定期维护:定期对历史表进行维护,例如删除过期的数据、优化索引等,以确保拉链表的性能和存储空间的有效利用。

需要注意的是,拉链表在数据仓库中的应用可能因具体需求和场景而有所不同。因此,在实际制作拉链表时,建议根据数据仓库的设计规范、业务需求和数据特点进行调整和优化。同时,也要确保数据的完整性、一致性和准确性。

参考:漫谈数据仓库之拉链表(原理、设计以及在Hive中的实现)_拉链表实现方式_小强签名设计的博客-CSDN博客

二、什么是拉链表

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

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

1. 拉链表的使用场景

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

  1. 有一些表的数据量很大,比如一张用户表,大约10亿条记录,50个字段,这种表,即使使用 ORC 压缩,单张表的存储也会超过100G,在 HDFS 使用双备份或者三备份的话就更大一些。
  2. 表中的部分字段会被 update 更新操作,如用户联系方式,产品的描述信息,订单的状态等等。
  3. 需要查看某一个时间点或者时间段的历史快照信息,比如,查看某一个订单在历史某一个时间点的状态。
  4. 表中的记录变化的比例和频率不是很大,比如,总共有10亿的用户,每天新增和发生变化的有200万左右,变化的比例占的很小。

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

  • 方案一:每天只留最新的一份,比如我们每天用Sqoop抽取最新的一份全量数据到Hive中。
  • 方案二:每天保留一份全量的切片数据。
  • 方案三:使用拉链表。
拉链表

  拉链表在使用上基本兼顾了我们的需求。
  首先它在空间上做了一个取舍,虽说不像方案一那样占用量那么小,但是它每日的增量可能只有方案二的千分之一甚至是万分之一。
  其实它能满足方案二所能满足的需求,既能获取最新的数据,也能添加筛选条件也获取历史的数据。

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

三、拉链表的设计和实现
1. 如何设计一张拉链表

我们先看一下在 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’。(此处要好好理解,是拉链表比较重要的一块。 where条件筛选当前有效数据,开始日期小于等于当前日期并且结束日期大于等于当前日期,则为有效。
2. 在Hive中实现拉链表

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

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

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

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

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

  1. 我们可以监听 Mysql 数据的变化,比如说用 Canal,最后合并每日的变化,获取到最后的一个状态。
  2. 假设我们每天都会获得一份切片数据,我们可以通过取两天切片数据的不同来作为每日更新表,这种情况下我们可以对所有的字段先进行 concat,再取 md5,这样就 ok 了。
  3. 流水表!有每日的变更流水表。
  4. 通过 etl 工具对操作型数据库按照时间字段增量抽取到 ods 或者数据仓库(每天抽取前一天的数据),形成每天的增量数据(实际中使用最多的情形)

(1)拉链表实现方式一

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';
)

现在我们假设我们已经已经初始化了 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
(2)拉链表实现方式二

操作型数据库的用户表结构:

CREATE EXTERNAL TABLE ods.user ( user_num STRING COMMENT '用户编号', mobile STRING COMMENT '手机号码', reg_date STRING COMMENT '注册日期' ,last_modify_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';

每天增量抽取的用户表结构和抽取条件:

  1)表结构和上面的表结构保持一致,我们取表名为 ods.user_update

  2)增量抽取条件:select * from ods.user where last_modify_date = '$date'

拉链表:

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

CREATE EXTERNAL TABLE dws.user_his ( user_num STRING COMMENT '用户编号', mobile STRING COMMENT '手机号码', reg_date STRING COMMENT '用户编号',last_modify_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:

1)

merge into dws.user_his tar 
using
(select user_num,mobile from ods.user_update 
) sou on tar.user_num=sou.user_num 
and tar.mobile=sou.mobile 
and tar.t_start_date < '$date' 
and tar.t_end_date >  '$date' 
when matched then 
update set tar.t_end_date='9999-12-31';

按照主键筛选,在 dws.user_his 表中出现过的并且现在为有效数据的,全部更新为闭链数据。

INSERT  TABLE dws.user_his 
SELECT C.user_num, C.mobile, C.reg_date, c.last_modify_date'2017-01-02' AS t_start_time, '9999-12-31' AS t_end_time FROM ods.user_update AS C;

比如我们要1月2号的数据,取出来的数据为 select from user where t_start_date <= ‘2017-01-02’ and t_end_date >= ‘2017-01-02’

与1月2号数据完全一致。

1. 拉链表和流水表

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

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

2. 查询性能

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

  1. 在一些查询引擎中,我们对start_date和end_date做索引,这样能提高不少性能。
  2. 保留部分历史数据,比如说我们一张表里面存放全量的拉链表数据,然后再对外暴露一张只提供近3个月数据的拉链表。
2. 备用方案:

  可以采用备份的方案,保证无误和可行。(保存增量数据,并对 t_dw_orders_his 表每个月备份一次全量数据。如需回滚,最多重跑30天数据即可)

六、总结

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

  1. 使用拉链表的时候可以不加 t_end_date,即失效日期,但是加上之后,能优化很多查询。
  2. 可以加上当前行状态标识,能快速定位到当前状态。
  3. 在拉链表的设计中可以加一些内容,因为我们每天保存一个状态,如果我们在这个状态里面加一个字段,比如当天修改次数,那么拉链表的作用就会更大。

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

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

相关文章

LeetCode----84. 柱状图中最大的矩形

题目 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例 1: 输入:heights = [2,1,5,6,2,3] 输出:10 解释:最大的矩形为图中红色区域,面积为 10 示例 2: 输入: heights =…

基于SSM的理发店管理系统

基于SSM的理发店管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringSpringMVCMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 主页 公告信息 管理员界面 用户界面 摘要 基于SSM&#xff08;Spring、Spring MVC、…

基于springboot漫画动漫网站

基于springbootvue漫画动漫网站 摘要 基于Spring Boot的漫画动漫网站是一个精彩的项目&#xff0c;它结合了现代Web开发技术和漫画爱好者的热情。这个网站的目标是为用户提供一个便捷的平台&#xff0c;让他们能够欣赏各种漫画和动漫作品&#xff0c;与其他爱好者分享他们的兴趣…

mfc140u.dll丢失怎么修复,mfc140u.dll文件有什么作用

今天我想和大家分享的是关于mfc140u.dll文件丢失的解决方法。在我们使用电脑的过程中&#xff0c;有时候会遇到一些错误提示&#xff0c;其中比较常见的就是“无法找到mfc140u.dll文件”。那么&#xff0c;这个文件是什么呢&#xff1f;它有什么作用呢&#xff1f; 首先&#…

模型实际训练笔记2-VGG

1、VGG简介&#xff1a; VGG网络是由牛津大学的视觉几何组&#xff08;visual geometry group&#xff09;首次提出来的。 VGG 网络&#xff0c;也称为Visual Geometry Group网络&#xff0c;是计算机视觉领域的一个深度卷积神经网络架构。它于2014年由牛津大学的研究团队开发…

SpringCloud-Alibaba-Nacos2.0.4

SpringCloud-Alibaba-Nacos2.0.4 SpringCloud Alibaba版本选择&#xff08;截止到2023年3月12日&#xff09; Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2021.0.4.0*Spring Cloud 2021.0.42.6.11 SpringCloud Alibaba-2021.0.4.0组件版本关系 S…

Ant Design Vue Table 表格内容高度自适应+固定表头踩坑

前言 对于非专业前端开发者来使用 Ant Design UI 组件来开发企业级后台管理系统来说是非常不错的选择&#xff0c;但这并不意味着我们能够用好这个框架&#xff0c;因为 UI 交互上和有许多细节上的问题对于非专业前端来说并不容易解决&#xff0c;最近在使用 Table 组件时就遇…

多路转接之epoll

本篇博客介绍&#xff1a; 多路转接之epoll 多路转接之epoll 初识epollepoll相关系统调用epoll的工作原理epoll服务器编写成员变量构造函数 循环函数HandlerEvent函数epoll的优缺点 我们学习epoll分为四部分 快速理解部分概念 快速的看一下部分接口讲解epoll的工作原理手写epo…

软件测试之用例篇(万能公式、具体方法)

目录 1. 概念 2. 万能公式 3.具体设计测试用例的方法 &#xff08;1&#xff09;等价类 &#xff08;2&#xff09;边界值 &#xff08;3&#xff09;判定表(因果图) &#xff08;4&#xff09;场景设计法 &#xff08;5&#xff09;正交法 如何使用 allparis 生成正交…

洞见UI自动化测试

随着软件行业的不断发展&#xff0c;建立一个完善的自动化测试体系变得至关重要。自动化测试包括三个方面&#xff1a;UI前端界面&#xff0c;Service服务契约和Unit底层单元如下图&#xff1a; 越是底层的测试&#xff0c;运行速度越快&#xff0c;时间开销越少&#xff0c;金…

【零参考GAN:Pansharpening】

ZeRGAN: Zero-Reference GAN for Fusion of Multispectral and Panchromatic Images &#xff08;用于多光谱和全色图像融合的零参考GAN&#xff09; 本文提出了一种融合低空间分辨率多光谱(LR MS)和高空间分辨率全色(PAN)图像的新的全色锐化方法–零参考生成对抗网络(ZeRGAN…

(一)、ts 基础类型 及class类举例字符雨和实现vue的挂在#app

文章目录 前言环境执行依赖node.js一、基础数据类型二、任意类型三、接口和对象类型四、 数组类型五、函数重载六、类型断言断言联合类型交叉类型 七、内置对象-Promise基础对象DOM和BOMPromise ts化代码雨案例 八、Class类(派生类和抽象类)派生类 abstract抽象类 classClass简…

自定义SpringBoot启动图标

在SpringBoot项目的resources目录下创建banner.txt文件 在https://www.bootschool.net/网站上复制Ascll艺术字&#xff08;图&#xff09;粘贴到banner.txt中保存。 启动项目就会加载 可以修改颜色&#xff0c;和版本号 ${application.version} 输出版本 ${spring-boot.v…

「软件设计师」 2023年上半年上午真题解析

「软件设计师」 2023年上半年上午真题解析 提示&#xff1a;系列被面试官问的问题&#xff0c;我自己当时不会&#xff0c;所以下来自己复盘一下&#xff0c;认真学习和总结&#xff0c;以应对未来更多的可能性 关于互联网大厂的笔试面试&#xff0c;都是需要细心准备的 &…

8. 一文快速学懂常用工具——Linux命令(上)

本章讲解知识点 引言 指令学习 本专栏适合于软件开发刚入职的学生或人士&#xff0c;有一定的编程基础&#xff0c;帮助大家快速掌握工作中必会的工具和指令。本专栏针对面试题答案进行了优化&#xff0c;尽量做到好记、言简意赅。如专栏内容有错漏&#xff0c;欢迎在评论区指…

Debug技巧-不启用前端访问后端

在日常开发中&#xff0c;我们经常会遇到各种问题需要调试&#xff0c;前后端都启动需要耗费一定的时间和内存&#xff0c;方便起见&#xff0c;可以直接用抓包数据访问后端&#xff0c;这里我们需要用到Postman或者ApiFox 抓包数据 在系统前台触发后端请求&#xff0c;在控制…

MyBatis入门

MyBatis是一款优秀的持久层框架&#xff0c;用于简化JDBC开发 持久层&#xff1a; 负责将数据保存到数据库的那一层代码 我们会将操作数据库的Java代码作为持久层&#xff0c;而MyBatis就是对jdbc代码进行了封装。 JavaEE三层架构&#xff1a;表现层、业务层、持久层 框架&…

mysql之索引

一、索引的概念 1、索引&#xff1a;是一个排序的列表&#xff0c;列表当中存储的是索引的值和包含之值的数据所在行的物理地址 2、主要作用&#xff1a;快速查找&#xff0c;加快查询速度 3、索引的缺点&#xff1a;索引也占用额外的磁盘 &#xff08;1&#xff09;innodb…

Stable Diffusion WebUI扩展openpose-editor如何使用

先上地址: GitHub - fkunn1326/openpose-editor: Openpose Editor for AUTOMATIC1111s stable-diffusion-webuiOpenpose Editor for AUTOMATIC1111s stable-diffusion-webui - GitHub - fkunn1326/openpose-editor: Openpose Editor for AUTOMATIC1111s stable-diffusion-webu…

[SpringCloud | Linux] CentOS7 部署 SpringCloud 微服务

目录 一、环境准备 1、工具准备 2、虚拟机环境 3、Docker 环境 二、项目准备 1、配置各个模块&#xff08;微服务&#xff09;的 Dockerfile 2、配置 docker-compose.yml 文件 3、Maven 打包 4、文件整合并传输 三、微服务部署 1、部署至 Docker 2、访问微服务 四…