首页 > 其他分享 >数据仓库之订单拉链表实战

数据仓库之订单拉链表实战

时间:2023-06-03 09:15:14浏览次数:28  
标签:实战 03 01 拉链 数据仓库 订单 2026 time

什么是拉链表

针对订单表、订单商品表,流水表,这些表中的数据是比较多的,如果使用全量的方式,会造成大量的数据冗余,浪费磁盘空间。

所以这种表,一般使用增量的方式,每日采集新增的数据。

在这注意一点:针对订单表,如果单纯的按照订单产生时间增量采集数据,是有问题的,因为用户可能今天下单,明天才支付,但是Hive是不支持数据更新的,这样虽然MySQL中订单的状态改变了,但是Hive中订单的状态还是之前的状态。

想要解决这个问题,一般有这么几种方案:

  • 第一种:每天全量导入订单表的数据,这种方案在项目启动初期是没有多大问题的,因为前期数据量不大,但是随着项目的运营,订单量暴增,假设每天新增1亿订单,之前已经累积了100亿订单,如果每天都是全量导入的话,那也就意味着每天都需要把数据库中的100多亿订单数据导入到HDFS中保存一份,这样会极大的造成数据冗余,太浪费磁盘空间了。
  • 第二种:只保存当天的全量订单表数据,每次在导入之前,删除前一天保存的全量订单数据,这种方式虽然不会造成数据冗余,但是无法查询订单的历史状态,只有当前的最新状态,也不太好。
  • 第三种:拉链表,这种方式在普通增量导入方式的基础之上进行完善,把变化的数据也导入进来,这样既不会造成大量的数据冗余,还可以查询订单的历史状态。

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

下面就是一张拉链表,存储的是用户的最基本信息以及每条记录的生命周期。

我们可以使用这张表拿到当天的最新数据以及之前的历史数据

用户编号	手机号码	start_time	end_time	解释
001	1111	2026-01-01	9999-12-31	初始数据
002	2222	2026-01-01	2026-01-01	初始数据
003	3333	2026-01-01	9999-12-31	初始数据
002	2333	2026-01-02	9999-12-31	修改
004	4444	2026-01-03	9999-12-31	新增

说明:
start_time 表示该条记录的生命周期开始时间,end_time 表示该条记录的生命周期结束时间;
end_time ='9999-12-31’表示该条记录目前处于有效状态;
如果查询当前所有有效的记录,则使用 SQL

select * from user where end_time ='9999-12-31'

如果查询 2026-01-02 的历史快照【获取指定时间内的有效数据】,则使用SQL

select * from user where start_time <= '2026-01-02' and end_time >= '2026-01-02'

这就是拉链表。

如何制作拉链表

那针对我们前面分析的订单表,希望使用拉链表的方式实现数据采集,因为每天都保存全量订单数据比较浪费磁盘空间,但是只采集增量的话无法反应订单的状态变化。

所以需要 既采集增量,还要采集订单状态变化了的数据。

针对订单表中的订单状态字段有这么几个阶段

未支付
已支付
未发货
已发货

在这我们先分析两种状态: 未支付和已支付。
我们先举个例子:
假设我们的系统是2026年3月1日开始运营的
那么到3月1日结束订单表所有数据如下:

订单id	创建时间		更新时间		订单状态	解释
001	2026-03-01	null		未支付	新增
002	2026-03-01	2026-03-01	已支付	新增

3月2日结束订单表所有数据如下:

订单id	创建时间		更新时间		订单状态	解释
001	2026-03-01	2026-03-02	已支付	修改
002	2026-03-01	2026-03-01	已支付	
003	2026-03-02	2026-03-02	已支付	新增

基于订单表中的这些数据如何制作拉链表?

实现思路
1:首先针对3月1号中的订单数据构建初始的拉链表,拉链表中需要有一个start_time(数据生效开始时间)和end_time(数据生效结束时间),默认情况下start_time等于表中的创建时间,end_time初始化为一个无限大的日期9999-12-31

将3月1号的订单数据导入到拉链表中。
此时拉链表中数据如下:

订单id	订单状态	start_time	end_time
001	未支付	2026-03-01	9999-12-31
002	已支付	2026-03-01	9999-12-31

2:在3月2号的时候,需要将订单表中发生了变化的数据和新增的订单数据整合到之前的拉链表中
此时需要先创建一个每日更新表,将每日新增和变化了的数据保存到里面

然后基于拉链表和这个每日更新表进行left join,根据订单id进行关联,如果可以关联上,就说明这个订单的状态发生了变化,然后将订单状态发生了变化的数据的end_time改为2026-03-01(当天日期-1天)
然后再和每日更新表中的数据执行union all操作,将结果重新insert到拉链表中

最终拉链表中的数据如下:

订单id	订单状态	start_time	end_time
001	未支付	2026-03-01	2026-03-01
002	已支付	2026-03-01	9999-12-31
001	已支付	2026-03-02	9999-12-31
003	已支付	2026-03-02	9999-12-31

解释:
因为在3月2号的时候,订单id为001的数据的订单状态发生了变化,所以拉链表中订单id为001的原始数据的end_time需要修改为2026-03-01。

然后需要新增一条订单id为001的数据,订单状态为已支付,start_time为2026-03-02,end_time为9999-12-31。

还需要将3月2号新增的订单id为003的数据也添加进来。

基于订单表的拉链表实现

下面我们开始实现:
1:首先初始化2026-03-01、2026-03-02和2026-03-03的订单表新增和变化的数据,ods_user_order(直接将数据初始化到HDFS中),这个表其实就是前面我们所说的每日更新表

注意:这里模拟使用sqoop从mysql中抽取新增和变化的数据,根据order_date和update_time这两个字段获取这些数据,所以此时ods_user_order中的数据就是每日的新增和变化了的数据。

2:创建拉链表,基于每日更新订单表构建拉链表中的数据
3:向拉链表中添加数据
3.1:添加2026-03-01的全量数据至拉链表(初始化操作)
3.2:添加2026-03-02的新增及变化的数据至拉链表
3.3:添加2026-03-03的新增及变化的数据至拉链表

拉链表的性能问题

拉链表也会遇到查询性能的问题,假设我们存放了5年的拉链数据,那么这张表势必会比较大,当查询的
时候性能就比较低了
可以用以下思路来解决:

  1. 可以尝试对start_time和end_time做索引,这样可以提高一些性能。
  2. 保留部分历史数据,我们可以在一张表里面存放全量的拉链表数据,然后再对外暴露一张只提供近3个月数据的拉链表。

商品订单数据数仓总结

数据库和表梳理

image

任务脚本梳理

image

标签:实战,03,01,拉链,数据仓库,订单,2026,time
From: https://www.cnblogs.com/strongmore/p/17369113.html

相关文章

  • 数据仓库项目介绍与分析
    项目效果展示本身我们这个数据仓库项目其实是一个纯后台项目,不过为了让大家能够更加直观的感受项目的效果,我们可以基于数据仓库中的数据统计一些指标进行展现。我们这个项目要讲的重点不是这个大屏,这个大屏只是一个效果,为了让大家感受更加直观一些而已,我们主要讲的是这些指标对......
  • Jenkins持续集成实战系列
    Spring常用注解redis视频集合,看完这些别说不会redisJenkins+Maven+SVN+Tomcat持续集成实v1战.docx1、传统网站部署流程.wmv2、主流网站部署流程及方法.wmv3、Jenkins持续平台安装.wmv4、Jenkins持续集成MAVEN讲解.wmv5、Jenkins持续集成JOB工程设置.wmv6、Jenkins持续集成网站构建......
  • 云原生第五周--k8s实战案例
    前言业务容器化优势:提高资源利用率、节约部署IT成本。提高部署效率,基于kubernetes实现微服务的快速部署与交付、容器的批量调度与秒级启动。实现横向扩容、灰度部署、回滚、链路追踪、服务治理等。可根据业务负载进行自动弹性伸缩。容器将环境和代码打包在镜像内,保证了测试......
  • Netty实战(十)
    (编解码器框架)一、什么是编解码器框架网络只将数据看作是原始的字节序列。但我们的应用程序则会把这些字节组织成有意义的信息。在数据和网络字节流之间做相互转换是最常见的编程任务之一。例如,我们可能需要处理标准的格式或者协议(如FTP或Telnet)、实现一种由第三方定义的专......
  • 新星计划|项目实训|SSM旅游网项目实战笔记一
    应邀请,特委派公司开发负责人张老师带队新星计划:SSM旅游网项目实训。现将实训的相关笔记分期发放,以供参考。如需要相关资料,可以博客尾部添加微信获取。一、实训介绍实训目的:其实通过实际的项目来检验大家的理论水平和实操水平,并同时通过实际的项目来积相应的项目经验。IT行业:主要特......
  • OpenMMLab AI实战营第二期
    OpenMMLabAI实战营笔记OpenMMLab简介OpenMMLab概述:中国人工智能计算机视觉算法体系每一种计算机视觉任务对应OpenMMLab的一个算法库内容:视觉基础库:MMCV,MMEngine算法框架:MMPretrain,MMDetection,MMDetection3D,...常用算法库:MMDetection(最有影响力的算法库......
  • JS逆向实战16——猿人学第20题 新年挑战-wasm进阶
    声明本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!网站https://match.yuanrenxue.cn/match/20网站分析首先进去网站,我们查看下接口发现有两个值是改变......
  • 分布式队列编程:模型、实战
    介绍作为一种基础的抽象数据结构,队列被广泛应用在各类编程中。大数据时代对跨进程、跨机器的通讯提出了更高的要求,和以往相比,分布式队列编程的运用几乎已无处不在。但是,这种常见的基础性的事物往往容易被忽视,使用者往往会忽视两点:使用分布式队列的时候,没有意识到它是队列。有具体需......
  • sparkSQL原理和使用——一般在生产中,基本都是使用hive做数据仓库存储数据,然后用spark
    一、sparkSQL概述1.1什么是sparkSQLSparkSQL是Spark用来处理结构化数据的一个模块,它提供了一个编程抽象叫做DataFrame并且作为分布式SQL查询引擎的作用。类似于hive的作用。1.2sparkSQL的特点1、容易集成:安装Spark的时候,已经集成好了。不需要单独安装。2、统一的数据访问方......
  • openmmlab-实战营二期-openmmlab概述课(一)
    openmmlab实战营-二期-openmmlab概述课(一)目录openmmlab实战营-二期-openmmlab概述课(一)openmmlab概述openmmlab各算法库详细介绍目标检测算法库MMDetection目标检测算法库MMYolo文字检测识别算法库MMOcr3D目标检测算法库MMDetection3D旋转目标检测算法库MMRotate图像分割算法......