基于MaxCompute的拉链表设计

本文涉及的产品
云原生大数据计算服务MaxCompute,500CU*H 100GB 3个月
云原生大数据计算服务 MaxCompute,5000CU*H 100GB 3个月
简介: 简单的拉链表设计

背景信息:

在数据仓库的数据模型设计过程中,经常会遇到这样的需求:
  1. 数据量比较大;
  2. 表中的部分字段会被update,如用户的地址,产品的描述信息,订单的状态、手机号码等等;
  3. 需要查看某一个时间点或者时间段的历史快照信息。(比如,查看某一个订单在历史某一个时间点的状态,比如,查看某一个用户在过去某一段时间内,更新过几次等等)
  4. 变化的比例和频率不是很大,比如,总共有1000万的会员,每天新增和发生变化的有10万左右;如果对这边表每天都保留一份全量,那么每次全量中会保存很多不变的信息,对存储是极大的浪费;
91a2da33-635f-4e7e-9ce7-e7a1ae783b96.png

综上所述:引入'拉链历史表',既能满足反应数据的历史状态,又可以最大程度的节省存储。
(备注:在阿里巴巴内部很大程度上是基于存储换计算来提供开发的效率及易用性,因为在当今,存储的成本远低于CPU和内存。因此在阿里巴巴内部会采用快照的方式将每日的全量数据进行快照,同时也会通过极限存储的方式,压缩率高,在合适的场景下,约能压缩为原始数据的1/30。)

Demo数据

以下只是demo如何在MaxCompute中实现拉链表,所以是基于一些假设:
  • 同一天中同一订单只有一个状态发生;
  • 基于20150821及之前的数据并没有同一个订单有两个状态的最简单场景模拟;
  • 且数据源在阿里云RDS for Mysql中。且表明为orders。

20150821以及之前的历史订单数据:

订单ID
创建时间
修改时间
状态
1
20150818
20150818
创建
2
20150818
20150818
创建
3
20150819
20150821
支付
4
20150819
20150821
完成
5
20150819
20150820
支付
6
20150820
20150820
创建
7
20150820
20150821
支付
8
20150821
20150821
创建

20150822订单数据:

订单ID
创建时间
修改时间
状态
1
20150818
20150822
支付
2
20150818
20150822
完成
6
20150820
20150822
支付
8
20150821
20150822
支付
9
20150822
20150822
创建
10
20150822
20150822
支付

20150823的订单数据:

订单ID
创建时间
修改时间
状态
1
20150818
20150823
完成
3
20150819
20150823
完成
5
20150819
20150823
完成
8
20150821
20150823
完成
11
20150823
20150823
创建
12
20150823
20150823
创建
13
20150823
20150823
支付
创建MaxCompute表

--ODS层:订单的增量数据表,按天分区,存放每天的增量数据
CREATE TABLE ods_orders_inc_d
(
 orderid BIGINT
 ,createtime STRING
 ,modifiedtime STRING
 ,o_status STRING
)
PARTITIONED BY (dt STRING)
LIFECYCLE 7;
--DW层:历史数据拉链表,存放订单的历史状态数据
CREATE TABLE dw_orders_his_d
(
 orderid BIGINT COMMENT '订单ID'
 ,createtime STRING COMMENT '订单创建时间'
 ,modifiedtime STRING COMMENT '订单修改时间'
 ,o_status STRING COMMENT '订单修改时间'
 ,dw_start_date STRING COMMENT '订单生命周期开始时间'
 ,dw_end_date STRING COMMENT '订单生命周期结束时间'
);
实现思路

  • 全量初始化:将2015-08-21及以前的全量历史数据通过全量方式同步至ODS并刷进DW层。
  • 增量更新:将2015-08-22、2015-08-23的全天增量数据以增量方式刷入下游数据。

全量初始化

  1. 创建节点任务:数据同步
  2. 选择调度类型:手动调度
  3. 配置数据同步任务:Mysql:Orders-->ODPS:ods_orders_inc_d
  4. where条件配置:modifiedtime <= '20150821'
  5. 分区值dt=20150821
提交调度系统,待数据同步任务执行成功后,再将ODS数据刷入DW。
创建SQL脚本:
INSERT overwrite TABLE dw_orders_his_d
SELECT orderid,createtime,modifiedtime,o_status,createtime AS dw_start_date,'99991231' AS dw_end_date
FROM ods_orders_inc_d
WHERE dt = '20150821';
数据如下:
订单ID
创建时间
修改时间
状态
start_date
end_date
1
20150818
20150818
创建
20150818
99991231
2
20150818
20150818
创建
20150818
99991231
3
20150819
20150821
支付
20150819
99991231
4
20150819
20150821
完成
20150819
99991231
5
20150819
20150820
支付
20150819
99991231
6
20150820
20150820
创建
20150820
99991231
7
20150820
20150821
支付
20150820
99991231
8
20150821
20150821
创建
20150821
99991231
通过以上步骤可以将2015-08-21及以前的历史全量数据一次性刷入DW和ODS中。

增量抽取并生成拉链表

  1. 创建工作流任务并选择周期性调度。
  2. 依次拖入数据同步节点任务和SQL任务。
  3. 在数据同步任务中where条件配置为:modifiedtime=${bdp.system.bizdate}
  4. 目标表ods_orders_inc_d分区配置为dt=${bdp.system.bizdate}
  5. 配置SQL节点,且为数据同步节点的下游节点。
--通过DW历史数据和ODS增量数据刷新DW表
insert overwrite table dw_orders_his_d 
SELECT a0.orderid, a0.createtime, a0.modifiedtime, a0.o_status, a0.dw_start_date, a0.dw_end_date
FROM (
	-- 对orderid进行开窗然后按照生命周期结束时间倒序排,支持重跑
	SELECT a1.orderid, a1.createtime, a1.modifiedtime, a1.o_status, a1.dw_start_date, a1.dw_end_date
	, ROW_NUMBER() OVER (distribute BY a1.orderid,a1.createtime, a1.modifiedtime,a1.o_status sort BY a1.dw_end_date DESC) AS nums
	FROM (
		-- 用历史数据与增量22日的数据进行匹配,当发现在22日新增数据中存在且end_date > 当前日期的就表示数据状态发生过变化,然后修改生命周期
		-- 修改昨日已经生命截止的数据并union最新增量数据到DW
		SELECT a.orderid, a.createtime, a.modifiedtime, a.o_status, a.dw_start_date  
			, CASE 
				WHEN b.orderid IS NOT NULL AND a.dw_end_date > ${bdp.system.bizdate} THEN ${yesterday}
				ELSE a.dw_end_date
			END AS dw_end_date
		FROM dw_orders_his_d a
		LEFT OUTER JOIN (
			SELECT *
			FROM ods_orders_inc_d
			WHERE dt = ${bdp.system.bizdate}
		) b
		ON a.orderid = b.orderid
		UNION ALL
		--2015-08-22的增量数据刷新到DW
		SELECT orderid, createtime, modifiedtime, o_status, modifiedtime AS dw_start_date
			, '99991231' AS dw_end_date
		FROM ods_orders_inc_d
		WHERE dt = ${bdp.system.bizdate}
	) a1
) a0 
-- 开窗口后对某个订单中生命周期为'9999-12-31'的取值并写入,防止重跑数据情况。
WHERE a0.nums = 1
order by a0.orderid,a0.dw_start_date;

备注:测试运行的时候,选择业务日期为20150822。也可以通过补数据方式,直接把20150822和20150823两天的增量数据刷入DW中。上面SQL中${yesterday}为自定义变量,其赋值为${yyyymmdd-1}
61bf77dd-a2bf-43c6-91ea-92b45ee2c79d.png
通过如上方式将20150822的增量数据刷入DW,如下所示:
订单ID
创建时间
修改时间
状态
start_date
end_date
1
20150818
20150818
创建
20150818
20150821
1
20150818
20150822
支付
20150822
99991231
2
20150818
20150818
创建
20150818
20150821
2
20150818
20150822
完成
20150822
99991231
3
20150819
20150821
支付
20150819
99991231
4
20150819
20150821
完成
20150819
99991231
5
20150819
20150820
支付
20150819
99991231
6
20150820
20150820
创建
20150820
20150821
6
20150820
20150822
支付
20150822
99991231
7
20150820
20150821
支付
20150820
99991231
8
20150821
20150821
创建
20150821
20150821
8
20150821
20150822
支付
20150822
99991231
9
20150822
20150822
创建
20150822
99991231
10
20150822
20150822
支付
20150822
99991231
通过同样的方式将2015-08-23日的数据增量输入DW,其结果为:
订单ID
创建时间
修改时间
状态
start_date
end_date
1
20150818
20150818
创建
20150818
20150821
1
20150818
20150822
支付
20150822
20150822
1
20150818
20150823
完成
20150823
99991231
2
20150818
20150818
创建
20150818
20150821
2
20150818
20150822
完成
20150822
99991231
3
20150819
20150821
支付
20150819
20150822
3
20150819
20150823
完成
20150823
99991231
4
20150819
20150821
完成
20150819
99991231
5
20150819
20150820
支付
20150819
20150822
5
20150819
20150823
完成
20150823
99991231
6
20150820
20150820
创建
20150820
20150821
6
20150820
20150822
支付
20150822
99991231
7
20150820
20150821
支付
20150820
99991231
8
20150821
20150821
创建
20150821
20150821
8
20150821
20150822
支付
20150822
20150822
8
20150821
20150823
完成
20150823
99991231
9
20150822
20150822
创建
20150822
99991231
10
20150822
20150822
支付
20150822
99991231
11
20150823
20150823
创建
20150823
99991231
12
20150823
20150823
创建
20150823
99991231
13
20150823
20150823
支付
20150823
99991231

如何使用拉链表

  • 查看某一天的全量历史快照数据。
SELECT *
FROM dw_orders_his_d
WHERE dw_start_date <= '20150822'
	AND dw_end_date >= '20150822'
ORDER BY orderid
LIMIT 10000;

  • 取一段时间的变化记录集合,如在20150822-20150823变化的记录。
SELECT *
FROM dw_orders_his_d
WHERE dw_start_date <= '20150823'
	AND dw_end_date >= '20150822'
ORDER BY orderid
LIMIT 10000;
  • 查看某一订单历史变化情况。
SELECT *
FROM dw_orders_his_d
WHERE orderid = 8
ORDER BY dw_start_date;
  • 取最新的数据。
SELECT *
FROM dw_orders_his_d
WHERE dw_end_date = '99991231'
关于基于历史拉链表回滚某一天或一段时间内的数据,还是一个相对比较复杂的话题,这个可以下载再谈。

相关实践学习
基于Hologres轻松玩转一站式实时仓库
本场景介绍如何利用阿里云MaxCompute、实时计算Flink和交互式分析服务Hologres开发离线、实时数据融合分析的数据大屏应用。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
目录
相关文章
|
24天前
|
SQL 分布式计算 DataWorks
DataWorks产品使用合集之如何将CSV文件从阿里云OSS同步到ODPS表,并且使用列作为表分区
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
DataWorks产品使用合集之如何将CSV文件从阿里云OSS同步到ODPS表,并且使用列作为表分区
|
11天前
|
存储 SQL 分布式计算
MaxCompute产品使用问题之upsert into语句如何在2.0事务表使用
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
26 10
|
11天前
|
分布式计算 DataWorks 大数据
MaxCompute产品使用问题之如何为某个用户授予仅对生产表的SELECT权限
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
11天前
|
机器学习/深度学习 分布式计算 DataWorks
MaxCompute产品使用问题之如何将DataWorks中的Hologres表数据导入到MaxCompute
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
10天前
|
SQL 分布式计算 DataWorks
MaxCompute产品使用问题之dts是否支持传输数据到mc主键表2.0
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
11天前
|
SQL 分布式计算 DataWorks
MaxCompute操作报错合集之表增加字段,提示创建表失败:DDL execute error, OdpsException: ODPS-0130071:[1,60] Semantic analysis exception - column,该怎么办
MaxCompute是阿里云提供的大规模离线数据处理服务,用于大数据分析、挖掘和报表生成等场景。在使用MaxCompute进行数据处理时,可能会遇到各种操作报错。以下是一些常见的MaxCompute操作报错及其可能的原因与解决措施的合集。
|
11天前
|
存储 机器学习/深度学习 分布式计算
MaxCompute产品使用问题之如何根据字段名或者字段注释查找到相关表
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
11天前
|
机器学习/深度学习 分布式计算 DataWorks
MaxCompute产品使用问题之如何恢复误删除生产环境的表
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
11天前
|
机器学习/深度学习 分布式计算 大数据
MaxCompute产品使用问题之ods层离线同步任务,数据源的一张表新增了字段。如何更改可以不影响当前节点和下游任务的运行
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。
|
11天前
|
存储 SQL 分布式计算
MaxCompute产品使用问题之如何方便快捷修改一个表的多个分区
MaxCompute作为一款全面的大数据处理平台,广泛应用于各类大数据分析、数据挖掘、BI及机器学习场景。掌握其核心功能、熟练操作流程、遵循最佳实践,可以帮助用户高效、安全地管理和利用海量数据。以下是一个关于MaxCompute产品使用的合集,涵盖了其核心功能、应用场景、操作流程以及最佳实践等内容。