以我当前的认知,数仓应该至少有下面两个职责:
下面详细说说这两点。
数据整合是为了解决各系统的异构问题。对于大体量的公司来说,往往会投入大量的资源解决“数据孤岛”问题。当一个公司大了以后,随着部门、分公司的增多,信息系统很难再使用统一的系统,每个分公司可能会各自的系统,各个系统中数据结构定义往往是差异,由于这种差异的存在,A、B两个系统不能识别对方的数据,这就我所说的“信息孤岛”。信息好像在一个孤岛上,不能在其他系统中流转。好比,不懂英文的人看不懂英文一样。于是乎我们需要一个翻译把各种语言翻译成英文,那么你有你懂英文,其他的语言所表达的含义也就能搞清楚了。我们今天所要说的数仓就好比数据的“翻译”。
我先来简单说说系统数据的异构性:
什么是表示协议的不同呢?我能接触到过的表示协议有:
上面几种表示协议不明白的请自行脑补。这几种协议到能表示相同的内容。
例如,我想用数据表示一个人的姓名、性别、年龄,不同的协议表示如下:
JSON 版:
{"name":"csdn","sex":"male","age":18}
xml 版:
<name>csdnname>
<sex>malesex>
<age>18age>
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 语句进行更新,需要注意的的是为了提高更新的效率,我们应该限定一下数据的更新范围,一般我们是根据时间了圈定要更新那些源系统的数据的。那么这个时间范围是如何限定呢?我们可以根据业务的场景中的每个订单的结束状态来查找最早的更新日期,从这个最左的更新日期到昨天的日期就是我们要更新的区间。这样做还是比较暴力的,因为会有相当数据的订单是不需要更新的,因为这些订单已经结束了。这时候我们可以现在一下订单号。
关系型数据库还是比较方便的,如果我们使用 hive 这样的数仓平台上构建数仓的话,就比较麻烦了,因为 hive 不支持行级的数据更新事务,所以我们需要更新和有变化订单在一起的所有订单。举个例子,hive 其实就是对一个文档做插入和整个文档的删除操作,假设我们有个订单 order1 ,在文件 A 中,A 中还有 orderN ,反正就是有其他好多“无辜”的订单,这里数的无辜是不需要更新的订单。这种情况下我们只能把文件 A 删掉,然后把最新的 ods 层的数据更新到 A 。 圈定更新的时间区间方法和关系型数据库查不多。
数据的留存问题其实比较明确,就是保留数仓的边界范围内的所以数据,也就从开业第一天到现在的数据。尽量多的保留数据。有的同学会说,这样会不会降低查询的速度,确实会造成影响的,但是我们可以通过加索引、分区的技术避开这个问题。