极限存储综合实践

 

前言

本文主要参考淘宝极限存储方案,并结合其他参考文章,总结实践。
 

 

整体演示 

user (源数据用户表,伪码):
create table user (
    id bigint,
    status int,
    create_time bigint,
    update_time bigint
)

  

user_all(历史拉链结果表,伪码) :

create table user_all (
    id bigint,
    status int,
    create_time bigint,
    update_time bigint
) partition by
(
    start_date string,
    end_date string
)

  

user_month_all(极限存储表,伪码):

create table user_month_all (
    id bigint,
    status int,
    create_time bigint,
    update_time bigint
) partition by
(
    start_date string,
    end_date string,
    month string
)

  

 

user 示例数据:
id status create_time update_time
11 1 1587268593 1587268593
12 1 1587268586 1587268586
11 2 1587268593 1587355026
12 2 1587268586 1587355078
11 3 1587268593 1588391793
12 3 1587268586 1588391899

 

首先回顾一下历史拉链表:

 

此数据演示两条数据在hive存储中的情况,id 11,12两条数据,分别在第一天创建,并在第二天修改。
接下来省略拉链具体sql操作,只描述全部按照正常拉链历史表的结果。

 

user_all 结果数据演示:
 
 
id status create_time update_time start_date end_date
11 1 1587268593 1587268593 2020-04-19 2020-04-20
12 1 1587268586 1587268586 2020-04-19 2020-04-20
11 2 1587268593 1587355026 2020-04-20 2020-05-02
12 2 1587268586 1587355078 2020-04-20 2020-05-02
11 3 1587268593 1588391793 2020-05-02 9999-12-31
12 3 1587268586 1588391899 2020-05-02 9999-12-31

 

可以看到拉链表可以查看任意时间快照的数据情况,但是相对的,在最坏情况下,根据 start_date 与 end_date的分区,最多可产生 (365*(365-1))/2+365 个分区,中间文件数=目录数*reduce数,会产生无数的小文件,这对计算性能影响相当的大。



接下来介绍极限存储思路以及注意的操作:
1.首先,按照月每次进行从新拉链操作。
2.在每个月的第二天,需要将上个月的未过期数据迁移到下一个月,并使用当月1日作为start_date。

 

user_month_all 结果演示:
5月2日执行结果

 

id status create_time update_time start_date end_date month
11 1 1587268593 1587268593 2020-04-19 2020-04-20 2020-04
12 1 1587268586 1587268586 2020-04-19 2020-04-20 2020-04
11 2 1587268593 1587355026 2020-04-20 2020-04-30 2020-04
12 2 1587268586 1587355078 2020-04-20 2020-04-30 2020-04
11 2 1587268593 1587355026 2020-05-01 2020-05-02 2020-05
12 2 1587268586 1587355078 2020-05-01 2020-05-02 2020-05
11 3 1587268593 1588391793 2020-05-02 9999-12-31 2020-05
12 3 1587268586 1588391899 2020-05-02 9999-12-31 2020-05

 

结论

虽然从结果看来,user_month_all与user_all结果差别不大,但是把时间线扩展到1年的情况下,分区数会大大的缩减,接下来是论证的过程。
1、2条数据表示4月份数据到4月份数据最后一次更改之前的快照。
3、4条数据表示4月份最后一次更改到下一次更改的快照。
5、6条数据4月份数据的有效数据迁移到5月份中,但是发现2号有更改记录,所以有效时间被修改为1-2号。
7、8条数据表示5月最新数据快照。
 
在此例子中,需要注意的是,此示例是实现跨月更改,所以需要考虑在5.2号数据会如何操作4月份的数据。
如果将4月份未过期数据直接迁移到5月起始日期中,可能会存在数据在4月最后修改时间到5月初中间空白,所以需要在跨月时如果数据一直未过期,需要将数据标记为4月末,然后5月份从新设置起始日期。

 

现在开始对比计算一下分区数:
user_all 拉链表:
根据start_date 与 end_date 的组合情况, 会存在 (365*(365-1))/2+365 = 66795个分区。
解释下此分区数计算逻辑,假设1.1日为start_date,对于end_date一共有365种选择,
以此类推,1.2日有365-1中选择,
根据高斯公式,所有分区数为 365 * (365 - 1)/ 2
然而需要考虑,在start_date中一直没有过期的数据,会需要设置一个独立的分区,整体需要365个分区。

 

user_month_all 极限存储:
按照月去分割拉链表。
根据start_date 与 end_date 的组合情况, 会存在 12*(31*(31-1)/2+31) = 5952 个分区。
解释下此分区数计算逻辑,假设每月有31天,1日为start_date,对于end_date一共有31种选择,
以此类推,2日有30中选择,
根据高斯公式,所有分区数为 31 * (31 - 1)/ 2
需要考虑,在start_date中一直没有过期的数据,会需要设置一个独立的分区,整体需要增加31个分区,
计算出一个月的分区数,在 乘以12 ,就为1年的分区总数。

 

可以根据结果可以看出,分区数大大的减少了。



极限存储的限制

 

此方案个人理解,其实可以理解为拉链表的变种,是从底层分区存储的角度优化SCD场景的实现方法。
但是也是有其使用的局限性,下面阐述一下此方案的优劣。

 

优势:

压缩存储成本,从存储的角度极大的提高计算效率。
保证对下游数据的透明性。

劣势:

相比于其他方案,此方案需要进行更多操作,产出效率不高。
从开发的角度来说,相比于历史拉链表上手难度要高。
如果频繁变更部分字段导致大量更新操作,依然选择使用极限存储的话,维度表需要进行拆解,例如进行垂直拆分维度或微型维度的方式进行优化。

 

个人总结

极限存储提供了一种新颖的底层分区存储方案,刚刚看到时会感叹开发者思路的奇妙。
但就像笔者对数据仓库开发的感受一样,基础技术都是相通的,维度建模的概念应用于业务实际开发时,不同的阶段和场景对于同一问题的解决方案是不同的,水无常形,综合方案的优劣,结合业务当前实际与后续的扩展性,选择合适当前业务场景的方案就是最好的方案。

 

参考文档:

http://www.zdingke.com/2018/05/24/%E6%8B%89%E9%93%BE%E8%A1%A8%E4%B8%8E%E6%9E%81%E9%99%90%E5%AD%98%E5%82%A8/
http://velocity.oreilly.com.cn/2011/ppts/velocityChina2011_TuHai.pdf
https://zhuanlan.zhihu.com/p/75070697

 

posted @ 2020-04-20 14:32  Eric-Ln  阅读(655)  评论(0编辑  收藏  举报