数据仓库分享

102 阅读8分钟
  • 想知道靓女征友会被多少人加好友么?
  • 想知道公司食堂的DAU日活么?

这些我都无法告诉你,因为我也不知道

不过如果你对这些问题感兴趣,那么你可能会希望了解下这些数据的可能来源——数据仓库

举个栗子

  • 小美:前两天我和闺蜜们在bbs发征友贴好多人加我们微信呀,但是有人反馈说加好友的频率太高加不上,呜呜呜,哥哥你帮我看看到底有多少人加我们呀

  • 开发小哥哥:好的!待我查找下数据!

开始开发

这个任务很简单,我要把所有人的加好友数量都计算出来,然后再过滤下她们的id就好了

  1. 第一步:找到原始数据表

咦?怎么原始数据表这么多,需要apply_friend member等多张表,而且涉及到的表字段也很多,还有很多无效数据,看来我需要增加一步清洗数据的工作

apply_friend表

idapply_nameapplied_name
1诸葛钢铁小美
2于小谦小可爱
3null小美
4朴一生小红
5朴一生小美
6朴一生小可爱

member表

idname
1诸葛钢铁
2于小谦
3小美
4null
5小红
6朴一生
  1. 第二步:清洗原始数据产出清洗数据表
SELECT * FROM apply_friend 
WHERE apply_name is not null

查询结果存入数据表 clean_apply_friend

idapply_nameapplied_name
1诸葛钢铁小美
2于小谦小可爱
4朴一生小红
5朴一生小美
6朴一生小可爱
SELECT * FROM member 
WHERE name is not null

查询结果存入数据表 clean_member

idname
1诸葛钢铁
2于小谦
3小美
5小红
6朴一生
  1. 第三步:进行SQL聚合
SELECT applied_name
       ,COUNT(applied_name) AS cnt
FROM(
  SELECT clean_apply_friend.id AS id 
        ,clean_apply_friend.apply_name AS apply_name
        ,clean_apply_friend.applied_name AS applied_name
  FROM clean_apply_friend 
  JOIN clean_member 
  ON clean_apply_friend.applied_name = clean_member.name
)
GROUP BY applied_name

查询结果存入数据表 result

applied_namecnt
小美2
小红1
  1. 第四步:为了更方便的使用图形化工具查找,我最好再加一个数据表用于出库,可以使用BI工具
SELECT applied_name
       ,cnt
FROM result

查询结果存入数据表 final_result 表,并且配置出库

什么是数据仓库

如果把刚刚每一步计算出来的数据表连起来,会看到下面的结构

如果我们给他们加上一些名词,就会发现这是一个比较清晰的层级结构

  • APP(Application):数据应用层
  • DM(Data Mart):数据集市层
  • DW(Data Warehouse):数据仓库层
  • ODS(Operational Data Store):数据运营层

如果DM数据仓库层不止2个数据表,还有更多可归类的数据表,那么就会形成主题

这就是数据仓库的雏形!

真实的数据仓库

  • 小美:小哥哥,你这个数据不太够,我想知道我的每日新增好友添加数量和从我使用微信以来每日累计以前的好友添加数量,可以帮帮我么

  • 开发小哥哥:好的!待我查找下数据!

上述小美的表达才是更接近真实的数据需求,通常数据需求会有比较常见的2大系列,分别是:

  1. 每日新增数据:
  • 11.17 加好友的数量是5个
  • 11.18 加好友的数量是6个
  1. 每日累计数据:
  • 从创建微信以来到11.16加好友的数量是95个
  • 从创建微信以来到11.17加好友的数量是100个
  • 从创建微信以来到11.18加好友的数量是106个

可以看到数据关系 95 + 5 = 100,100 + 6 = 106

如何计算每日新增和每日累计

为了完成上述两种统计数据,就要求线上数据必须每日同步增量数据,并根据数据日期ds字段进行区分

apply_friend 表

dsidapply_nameapplied_name
202109011诸葛钢铁小美
202109012于小谦小可爱
202109013null小美
202109014朴一生小红
202109025朴一生小美
202109026朴一生小可爱

可以看到前 4 条数据都是2021年9月1日出现的,后 2 条数据是2021年9月2日出现的

根据这样的表计算出每日新增的数据很容易,用ds作为查询条件进行聚合即可,比如计算9月1日用户的申请的数量

SELECT COUNT(*) 
FROM apply_friend 
WHERE ds = 20210902
GROUP BY applied_name

而计算每日累计数据时,更建议清洗出一张全量数据表,并用其直接进行计算

什么是全量数据表

所谓的全量数据表指的是每天都存储从原始数据产生以来的所有数据,尤其是当存在状态变化时,全量数据表的存在尤为重要

比如:

apply_friend 表

dsidapply_nameapplied_namestatus
202109011朴一生小美申请中
202109012诸葛钢铁小美申请中
202109023诸葛钢铁小美已查看
202109024朴一生小红申请中
202109035诸葛钢铁小美已拒绝

对应的全量数据表为:

full_apply_friend 表

dsidapply_nameapplied_namestatus
202109011朴一生小美申请中
202109012诸葛钢铁小美申请中
202109021朴一生小美申请中
202109023诸葛钢铁小美已查看
202109024朴一生小红申请中
202109031朴一生小美申请中
202109034朴一生小红申请中
202109035诸葛钢铁小美已拒绝

我们可以看到,9月2日,加入了9月1日的数据,9月3日又加入了1-2日的数据,并且过滤掉了多余的状态条数,也就是诸葛钢铁和小美的申请关系

上述数据关注小美相关的会发现,从9月1日-9月3日期间,诸葛钢铁申请小美好友的申请关系变化,申请中->已查看->已拒绝

如果我们统计9月1日小美累计处于申请中的好友申请数量,那么是2

统计9月2日小美累计处于申请中的好友数量,那么是1

为什么要建设数据仓库

数据仓库建设是为了解决很多数据计算的问题,其中包括

  • 数据依赖关系混乱,重复计算
  • 缺少数据计算规范
  • 数据产出效率低

数据依赖关系混乱,重复计算

看上图对比我们就可以知道,没有数据仓库时,数据依赖关系十分混乱,存在大量数据重复计算的问题,既浪费计算资源,又让后来的开发者无所适从,不知道应该如何继续开发

而有了数据仓库之后,计算任务整洁有序,便于维护和开发,也节省资源

缺少数据计算规范

数据开发和普通的代码开发一样,也应该树立上图的开发规范,保证数据计算的顺序性,模块合理划分,也能够产生高质量的数据

一个遵循了数据规范的数据仓库图表示例,如下图所示

数据产出效率低

数据产出效率低,是有很多方面引起的问题,这里专门讲解下如何优化数据仓库性能

如何优化数据仓库性能

数据仓库性能可能常常面临的是两方面问题

  1. 计算任务性能差(一个任务计算8个小时,非常久)
  2. 计算资源消耗多(一个任务占用80%的CPU、内存)

那么下面举一些实际开发的样例,来说明优化方案

优化1:全量数据清洗优化

优化方案简介和效果:

优化前的SQL:

优化后的SQL:

每日增量数据+前一日全量数据=每日全量数据,通过这样的计算方式,可以避免以前的重复数据计算,增加数据清洗效率

优化2:全量数据多维度聚合优化

优化方案简介和效果:

优化前的SQL:

优化后的SQL:

uin是用户微信号的唯一id标识,因为用户微信号的数量相对有限,可以固定在十几亿左右,所以做一步中间聚合可以大大减少数据量,进而达到减少数据计算时间的目的

优化3:多表数据UNION优化

优化方案简介和效果:

优化前的SQL:

优化后的SQL:

每次取出数据时都会根据ds字段取出全部分区内容,如果分区被多次取出并且在同一个任务里面,那么比如这个分区的数量是10亿,取了8次就是80亿,进而会导致资源占用量急速增大,导致集群其他任务无法正常运行

优化4:多维度聚合步骤拆分

优化方案简介和效果:

优化前的SQL:

优化后的SQL:

当使用rollup进行多维度聚合时,FROM子句中包含子查询或者join时会导致重复计算的现象,进而降低数据产出效率

小结

数据仓库是为了更高效产出统计数据的工作,如果你对小美的好友数据好奇,不妨来了解了解数据仓库