一、前言
做过电商开发的同学对订单的业务应该不陌生,比如对一条订单数据来说,通常会有一个类似于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
构建拉链表,通过时间标记发生变化的数据的每种状态的时间周期,如下图表中数据所示,它大意就是,当一条数据中的关键业务标识字段发送了变化,将新增加一条数据,将这条数据的过期时间设置的非常大,作为这条数据的边界,同样主键的数据再次过来的时候,在新增的一条记录中只需要记录变化的字段即可;关于拉链表,下文将做详细的讲述;
免责申明:
本文系转载,版权归原作者所有,如若侵权请联系我们进行删除!
《数据治理行业实践白皮书》下载地址:https://fs80.cn/4w2atu
《数栈V6.0产品白皮书》下载地址:https://fs80.cn/cw0iw1
想了解或咨询更多有关袋鼠云大数据产品、行业解决方案、客户案例的朋友,浏览袋鼠云官网:https://www.dtstack.com/?src=bbs
同时,欢迎对大数据开源项目有兴趣的同学加入「袋鼠云开源框架钉钉技术群」,交流最新开源技术信息,群号码:30537511,项目地址:https://github.com/DTStack