其他分享
首页 > 其他分享> > 数据仓库--拉链表

数据仓库--拉链表

作者:互联网

拉链表

记录历史数据的每个状态,记录一个事物从开始,一直到当前状态的所有变化的信息

拉链表通常是对账户信息的历史变动进行处理保留的结果

拉链表形成过程

订单当日全部数据和mysql中每天变化的数据拼接在一起,形成一个新的临时拉链表数据

用临时的拉链表覆盖旧的拉链表数据(这就解决了hive表中数据不能更新的问题)

拉链表就增加了两个字段信息:有效开始日期和有效结束日期

拉链表简单实例(转自知乎 https://zhuanlan.zhihu.com/p/75070697

用户表(user)

用户表的变化过程如下:

以上罗列了每次修改记录后用户表的变化情况,接下来会介绍拉链表如何实现,及优化的历程

拉链表概述

下面的表结构是用户表对应的拉链表(user_link) 的表结构:

其中相对于原始表增加两个字段分别为:生效日期和失效日期,这两个字段代表每条记录的有效区间

一般来讲,拉链表的更新是按天更新的。所以接下来我们分别看下7月1日和7月2日拉链表的记录

截止7月1日全量数据

当天只有A注册了用户,表数据如上表。其中生效日期为记录插入的时间(即2019-07-01)

同时由于这条记录是有效记录所以失效时间用一个很大的日期占位(即9999-12-31)

截止7月2日全量数据

用户A在7月2日更新过手机号码,此时拉链表会留下两条A的记录

一条是更新手机号之前(即2019-07-01日)的记录,并且失效时间更改为2019-07-02

一条是更新手机号码之后(即2019-07-02日)的记录,并且生效日期为2019-07-02,失效日期为9999-12-31

用户B在7月2日有两次操作,一次是注册,一次是更新手机号码

但是在拉链表中只保留当日最新的记录

查询方式

想要查询2019-07-02日的快照的查询语句如下:

select * from user_link where st_date<='2019-07-02' and end_date>'2019-07-02'

如果想要查询2019-07-01至2019-07-02的数据查询语句如下:

select * from user_link where st_date<='2019-07-02' and end_date>'2019-07-01'

简单的分区方式(hive分区)

以上的拉链表是没有分区的,在查询的时候查询效率会非常低

我们可以用生效日期失效日期作为分区字段来提升查询效率

create table if not exit user_link_partition(
    name            string,
    phone           string,
    sign_up_date    string,
    modify_time     string
) 
partitoned by (start_date string, end_date string)
stored as orc;

生效日期和失效日期作为分区字段

带来查询效率优势的同时也引入了一些问题

基于以上的问题我们可以做一些优化

按月分区

每月2日把上一月的所有还未失效的数据归并到1日的分区中,并且把start_date改为1日

7月2日在计算2019-07-01日的数据时除了会处理从原始表抽取过来数据之外还会把拉链表中6月30日还未失效的数据抽取过来

此方式可以保证生效和失效日期不会跨月,即使数据还未失效也会移动到新的月份

支持delete

在之前的更新拉链表的方式都是基于原始表的数据,这会导致无法感知数据删除

如果要感知删除的数据成本会很高

一个简单的方式是同步binlog数据,binlog中会标记每条数据的转态,以此方式就能快速知道删除的数据

在7月3日的拉链表中就可以通过主键找到要删除的记录,并且把失效日期改为2019-07-03,以此实现拉链表的删除

标签:02,07,拉链,--,数据仓库,日期,2019,数据
来源: https://www.cnblogs.com/YC-L/p/14454632.html