数仓建设几个关键问题

数仓的功能

以我当前的认知,数仓应该至少有下面三个职责:

  • 数据整合
  • 统一口径
  • 提高数据分析的效率

下面详细说说这三点。

数据整合

数据整合是为了解决各系统的异构问题。对于大体量的公司来说,往往会投入大量的资源解决“数据孤岛”问题。当一个公司大了以后,随着部门、分公司的增多,信息系统很难再使用统一的系统,每个分公司可能会各自的系统,各个系统中数据结构定义往往是差异,由于这种差异的存在,A、B两个系统不能识别对方的数据,这就我所说的“信息孤岛”。信息好像在一个孤岛上,不能在其他系统中流转。好比,不懂英文的人看不懂英文一样。于是乎我们需要一个翻译把各种语言翻译成英文,那么你有你懂英文,其他的语言所表达的含义也就能搞清楚了。我们今天所要说的数仓就好比数据的“翻译”。

我先来简单说说系统数据的异构性:

  1. 表示协议的不同
  2. 命名的不同

什么是表示协议的不同呢?我能接触到过的表示协议有:

  • JSON(最常见)
  • xml
  • cvs
  • dsv
  • binlog
  • 其他

上面几种表示协议不明白的请自行脑补。这几种协议到能表示相同的内容。
例如,我想用数据表示一个人的姓名、性别、年龄,不同的协议表示如下:

JSON 版:

{"name":"csdn","sex":"male","age":18}

xml 版:

<name>csdn</name>
<sex>male</sex>
<age>18</age>

cvs 版:

中间试验 TAB 隔开
name	sex	age
csdn	male	18

举上面的例子,就是为了说明什么是表示协议的不同。

除此之外,命名可能还不一样,例如,name 在 A 系统是 user_name ,在 B 系统是 name。

还有更复杂的差异,在这里就不细说了。

为了解决上面提到的差异性,数仓需要把从各个系统中的数据转换成相同的格式,例如 csv、orc 等等。

统一口径

如果把“数据整合”比作是翻译的工作,那么统一口“让数据说普通话”。举个例子,每个销售系统中都有订单状态这么字段,例如,A 系统的订单状态有 1、2、3 这三种,B 系统有 4、5、6 三种,假设他们表达的意思都是一样的,那么数据仓库就要想办法,让数据在表达相同语义的时候,使用相同的语言。例如,可以对 B 系统的数据做一个转换,即4→1,5→2,6→3。这样是不是让数据说了普通话。

做数据处理的工作有好多,常见的有 excel、实现标准 sql 的处理平台、ETL 工具等等。excel 最为常见,也是国家计算机二级要考的科目,有句话说的特别有道理,不会 excel 就是文盲,屏幕前的你是否同意这个观点,反正我是比较认同的。然后就是的实现 sql 的数据处理平台,这是数仓主要载体,大多数的数仓都是跑在上面的。这些平台中关系型数据库包括 Oracle 、SqlServer、MySQL,到了大数据技术这个领域,有像hive 这样的数仓工具,还有想 impala、flink、spark 这样的计算引擎,不过总体来说,hive、impala、flink、spark 都是数据计算引擎,解决的是大数据的计算问题,而存储都非 hdfs 了。hdfs 是 Hadoop 的重要组成部分,解决了大数据场景下的数据存储问题。其实对于我们学习数仓来说,知道这些应该就够了。毕竟,我们更应该关注的是“怎么让数据说普通话”。从这个角度讲,我们不得不学习的是 sql ,学会了 sql 就好比学会了说英语,因为大部分的数据处理平台都已经实现了 sql 的接口,所以要好好学 sql ,举个例子,其实在 hive 之前有个叫 pig 的计算平台搞的挺火,但是 hive 出来了,pig 的没没有多少人用了,一个很大因素是,pig 平台上不能运行 sql 语句,而 hive 可以,于是在关系型数据上做数仓的人几乎可以没有任何学习成本的情况下,进入到大数据开发的领域。

上面啰嗦的有点多了,下面开始总结一下如何建设数据仓库。先说基本的几个问题。

  • 划分业务的边界
  • 业务主体之间的关系
  • 数仓的维度
  • 数仓的指标问题
  • 数据仓数据的更新策略
  • 数仓的留存问题

提高数据分析的效率

数仓边界划分

如果要想做数仓,我们先要把我们所在行业的业务流程搞清楚。那什么是搞清楚呢?

第一,首先,需要了解业务流程。也就是你所在公司主营业务中有多少个环节,各个环节中有多少个角色参与,各个角色会做什么样的动作,动作产生了,那么在系统里面会生成对应的什么样的数据。

第二,我们对整个流程进行划分,有可能我们的场景的比较简单,我用一个数仓就可以解决问题。如果我们的业务流程比较长的话,我有可能会将整个业务流程切分成几个子流程,真对这几个子流设计、开发数仓。举个例子,我们可以想想,我们是在一家做外卖的公司做数仓,那我们有几个环节呢?我们可以意淫一下,下单→派单→接单→到店→配送→配送完成,参与的角色有,顾客、派单平台、配送员。如果有客服问题,外卖平台的客服人员也可能参与进来。真是的场景应该比这还复杂,但是这样也能说明问题了。假设我们有变成了运营人员,我们如何指定正确的市场策略来增加我们的顾客满意度,如何衡量的政策执行是否好?这都需要数据来支持的,数据好像千里眼,将业务运营的整体情况体现出来。基于这一点,我们需要看我们每天挣钱了吗?如果挣钱了,我们挣了多少,如果赔钱了,赔了多少。还有我们能改善哪个环节来提升我们的业绩。好像又偏题了,不过我们肯定知道,我们可以提升配送员的准时率,来提升顾客的购物体验,那我们我们可以分析一下,影响准时率的有那几个因素,店家是否及时准备好商品,配送员接单后,是否及时取货,配送员规划的路线是否有问题等等问题。如果我们想解决这些问题的话,我们的数仓应该从用户下单到配送完成。所以我们需要先搞清楚我们要解决什么问题,只要这个问题解答了,我们就可以确认数仓模型的边界了。

当我们圈定了数仓的业务范围,我们就要像写小说一样搞清楚数仓中的时间、地点、人物。

业务主体之间的关系

业务主体之间的关系也就是小说里面的人物关系。小说可以通过人物之间的对话、相互的动作来阐述人物之间的关系。到了我们数仓里面,讲求的就不是文学上的造诣,而是讲求标准化、易懂化。俗话说有图有真相,描述业务主体之间的关系最好的办法就是使用 ER 图了。

这里推荐一下如何画 ER 图,最简单的就是使用 Visio 画了,可以在网上搜出好多Visio 的使用方法。本人 ER 图画的不多,就不在这里意淫了。但是还是推荐一篇文章

数仓的维度

一说到维度,我们就进入到了数仓表的设计范畴了。维度代表了的数仓所描述的对象以及对象的属性。 维度好比小说里面人物的属性,包括技能、外表等,好像是介绍英雄一样。拿配送员来说,对于配送员的来说,最基本的属性就是工号、登陆号、姓名、电话号码。其中工号是不能少的,工号好比是配送员在在我们数仓系统里面的身份证,一般的情况下,我们是通过工号来区分每个配送员的。其他的如年龄、性别,即使我们空着,也是要有这些字段,因为我们要做的通用一些,更多是从行业的角度来思路字段的设计。

有一种建模的思路就是维度建模,其核心就是围绕业务主体进行分析的设计思路。

数仓的指标

上文谈了我对维度的理解,维度是讨论数仓的分析对象比较固定的属性。更多从生理、社会的属性去设计。指标应该是描述对象的动态的属性,是讨论对象做为公司的一个螺丝钉工作的质量,也就是工作质量的量化。例如,一个配送员的配送单量,这可以衡量配送员工作的量。然后配送员的投诉数、配送超时率这可以衡量工作的质。一个正规的数据团队一定会有个指标库。指标库的作用是对数仓中所以指标做统一、清晰的定义。这个很关键,因为统一的指标定义是降低团队学习成本、沟通成本的基础。更重要的一点是现在的互联网公司都是铁打的营盘流水的兵,指标库也会降低交接的成本。

数仓的更新策略

当我们把维度和指标弄清楚以后,接下来一个重要的问题,就是数仓的更新策略问题了。那么什么是更新策略呢?请大家想这么一个问题,我们的数据都是从线上的业务系统来的,而且我们们一般是今天抽取昨天的数据。还是外卖的场景,一般情况下,我们下一个外卖的订单,在一天之内就能完成了,因为外卖的场景下,用户都是等着吃东西的,是希望能尽快的吃到东西。让我们想象做饭的场景,假设我 9 点出门,我昨天 10 点的时候,下一个 8 点送达的预约单。那么问题来了,数仓一般是抽取昨天一整天的 insert、update 的数据。我在当天从业务系统只能抽取到这个订单下单付款的数据。到了第二天,我们才能拿到这个订单配送开始、结束的信息。拿到这些信息之后我们我还要在这个订单下单、支付的基础上加入配送的信息。在关系型数据库我们可以使用 update 这样的 sql 语句进行更新,需要注意的的是为了提高更新的效率,我们应该限定一下数据的更新范围,一般我们是根据时间了圈定要更新那些源系统的数据的。那么这个时间范围是如何限定呢?我们可以根据业务的场景中的每个订单的结束状态来查找最早的更新日期,从这个最左的更新日期到昨天的日期就是我们要更新的区间。这样做还是比较暴力的,因为会有相当数据的订单是不需要更新的,因为这些订单已经结束了。这时候我们可以现在一下订单号。说了这么多,下面上一个大图来说明上面的场景:

ods 层数据更新的逻辑

上图中,某用户在 10.28 号下了一笔订单,在 10.29 号取消了订单。所以的在 10.28 和 10.29 号这笔订单的状态都发生了变化。这需要我们把这两个状态更新到 ods 层。首先,这里我们是根据增量的方式来了每天抽取源系统的数据,那么如何才能做到增量呢? 这里我是依据 update_time 这个字段来了判断的,一般的情况下,在源系统中,更新或者新增一条记录,都会更新 update_time 来记录更新或者新增操作的发生的时间戳。在抽取数据的时候,符合“昨日凌晨 < update_time < 昨日 23:59”条件的,都会更新到 stage 这层来的。stage 这层只是记录每天的增量数据。

下面要做的就是 stage 层的数据添加到 ods 层,这里讲的“添加”,不是是 append,是 upsert 操作。在关系型数据库还是比较方便的,在 mysql 有 replace into 操作, 在 SQLserver 有 merge into 操作。如果我们使用 hive 这样的数仓平台上构建数仓的话,就比较麻烦了,因为 hive 不支持行级的数据更新事务,所以还要想其他办法,一般情况下,在源系统的表中都会有一个主键存在,如果我们根据主键 + update_time 排个序,相同主键的记录根据主键倒序排列,我只需要取出第一次数据就可达到目的了。具体的做法就是 stage 和 ods 层先做一次 union all 操作,然后再做一次 row_number() over( partition by ID order by update_time desc ) as row_index ,再做一个 row_index = 1 的过滤。打完收工。

模型设计

大家都听说过,田忌赛马的故事,从这个故事里面,我总结了一个道理,同样的三匹马,只要重新设计了一下他们的结构,就会变腐朽为神奇。一切系统的要领就在于设计出巧妙的结构来适应需求。数仓的建设也不例外。

在设计业务系统时,一般是遵循三范式,在理解三范式就是表与表、行与行、列与列之间数据就高内聚,这也遵循闭包的原则,这种设计更够让表的设计简洁,容易理解,易于使用和维护。这也使得不同的数据都会放到不同的表里面,导致了数据变的分散。数仓说到底就是一个分析性系统的一部分,为了分析影响销售的因素,不但要使用销售的数据,还好使用售后、库存、配送等系统的数据。然后在数仓中,我会将销售相关的数据整合到一起,形成一个宽表。从字段上来看,宽表里面包含销售、售后、配送的字段。说到这里就引出了 DW 层的概念,也有叫 DWB 层,这一层重要任务就是完成数据整合的。这样有引出了另外一个概念——“复用”,精巧的设计一个重要的原则就是能够复用,减少重复工作。当我们计算一个报表的时候,肯定会做各种 join ,如果我们使用 ods 层开发报表也是可以的,但是每次开发报表都要写重复的表关联语句,是不是开发效率很低,而且每个报表都经过相同的 join 操作,对计算平台的资源也是一种浪费。 DW 层就解决了这个问题,计算一次,后面的 DM 层和 RPT 层都可以重复利用 DW 层做好的结果。

数据的留存

数据的留存问题其实比较明确,就是保留数仓的边界范围内的所以数据,也就从开业第一天到现在的数据。尽量多的保留数据。有的同学会说,这样会不会降低查询的速度,确实会造成影响的,但是我们可以通过加索引、分区的技术避开这个问题。

后期计划

  1. 数仓的分层,已经各层遇到的困难
  2. 构建数仓的人员是如何安排,人员配比, 设计规划
  3. 建模过程遇到的坑
  4. 数据一致性的问题。数仓各层之间的一致性。维度、指标口径是否一致。还有同层之间的相同指标口径是否一致。
  5. 数据复用性。
  • 6
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值