笔者先后在外企,互联网,金融行业工作,从最初的ODS,DM架构到后面ODS,DWD,DWS,ADS架构都有较深的理解和应用,甚至在相当长的时间内,数仓设计一直作为一个常规的面试题目,来考核各层级的数仓开发和架构师。然而在实际的沟通的交流中,发现很多同学虽然对同样的架构分层设计多多少少都能说出来一些,但是反过来再问为什么这样分层,答案就五花八门了。
这篇文章主要针对数仓设计来谈谈我的看法,因为不同的规模的公司对数仓建设的目的有差异,这里从架构师角度仅讨论中大型企业的数仓架构建设。本文主要以一问一答式来展开讨论。
1.一般用数仓来做什么?
这就要从数仓能解决的问题或者痛点来说,大型公司的业务相对复杂,随着公司业务的扩大,跨BU,跨BG的业务往来越来越多,而数据一般分散在各个部门,这样需要统一的平台来存储这样的跨系统的数据。此外,近年来分库分表等应用越来越多,仅通过传统关系型数据库做数据分析和挖掘已经不能满足要求。当然随着手机APP的大量使用,埋点等数据一般都以log日志方式存在,需要一个新的介质后者方案来解析这些数据,为了解决这个问题,数仓技术应运而生。 反过来讲,如果公司系统较为单纯,数据量比较小,传统关系型数据库以及完全可以满足数据检索和分析的需求,就不需要花成本来构建数仓。 其实构建数仓的原因还有很多,但无非是用一个更可靠的平台把分散的低价值的数据通过清洗,整合,分析挖掘使得数据的价值最大化。
2.为什么要建数仓?
数仓一般分为实时和离线数仓,现在绝大多数公司采用的是lambda架构来统筹管理实时和离线数据,那么就有这样一个问题,数仓能干啥? 首先历史数据备份,尤其是金融机构,客户的历史若干年的记录都需要保留,而如果放在源业务系统,数据量过大,此外很多历史数据是冷数据,不常使用。 其次,做报表,公司一般都有自己的经营指标,各部门有各种各样的报表需求,数仓中数据一般都是经过清洗整合过的,因此比较容易出一些统计类数据和指标。 还有就是做数据分析挖掘,比如通过交易和流量数据挖掘用户的偏好,通过用户的实时流量来做推荐,再就是构建特征宽表,来满足特定机器学习的需要。除了机器学习还有比较多的应用是多维分析,通过数仓中的宽表或者明细表来根据特别的维度进行聚合分析。 有一些系统会把复杂的计算逻辑在数仓中实现,然后再把结果数据,如风险变量等,再回传给到业务系统。
3.数仓分多少层比较合适
如果我给你一个具体的答案肯定会有各种不一致的意见,那么我换种方法来回答,也就是,根据你的需要来(不要打我)。 再我们设计数仓分层的时候,要考虑到公司或者部门的实际需要。如果你负责的仅仅是一个小部门的数据,而公司已经有一个数仓平台了。那么你或许仅需要构建一个你自己的应用层,或者集市层。所以接下来我讲的整个公司的数仓架构。这里再明确一下,这里的数仓是广义的数仓,而不是狭义的数仓层(对应上面的集市层)。以下我给出最可能的最小层级。
A.统一ODS层,这一层有一个关键字,是统一,也就是用通用的,全自动或者半自动化的技术来做,在oracle时代,构建ods层的目的除了把多个数据源做统一外,还有一个用途,就是把不同的codepage通过这一层来解析成统一的codepage,避免乱码。现在可选择的大数据同步技术也比较多,如datax,canal,kafka等。因为这一层的目的主要是把源系统的数据基本原样(有些数据敏感等级高不同步)的同步到大数据平台,因此比较容易进行方案的统一。因为是统一的工具来同步,所以清洗的功能较为有限,基于此,该层数据不建议直接对外暴露给到应用层。
B.dw层,这一层建设很有讲究,一般大的公司有公共IT部门,该部门会构建统一数仓,如主数据,如统一交易表,统一埋点 或者 标准维度表等。当然大一点的事业群或者事业部会构建自己的数仓层,有一些部门特有的业务数据。 所以这一层有以下关键字:清洗,拆分,整合,标准化,备份,隔离。清洗很好理解,不展开;拆分,举个例子,底层有统一的埋点表,但是自己所在部门或者业务不需要全部数据,仅需要抽取所需数据即可。 整合,同样举例说明,活动数据一般跨系统,需要把多个系统的活动数据从各子系统拿出来再做整合加工;标准化,数仓都是主题化的,这一层主要是面向业务过程来组织的,那么需要对模型进行标准化(表名,字段名,码值,元数据等);备份,因为一般ods层没有经过清洗,而这一层是经过清洗的,更适合保存历史数据(不排除有些公司把历史放在ods层,这里只讨论最佳实践);隔离,很多同学不是很理解隔离的重要性,在构建整个数仓的过程中,不可避免会发生源业务系统的表结构或者表本身发生变化,如果没有一个中间层进行隔离的话,如果对应的底表被多个下游表使用,那么模型的修改代价是非常大的。因此该层主要对原系统变更进行隔离,尽可能保证对外的模型接口不变。 dw层一般还会继续细分为 明细层和轻汇总层,模型中一般通过detail 或者aggr 关键字来区分,主要目的是统一口径。这里需要注意的是,dw层主要仍然是面向业务过程的(如浏览,下单),面向分析的主题(客户,客户行为等)一般放在集市层。因此这里的aggr主要是针对业务过程的轻汇总
C.集市层,这一层一个更直观的叫法是宽表层,为什么是宽表,主要是这一层存在的意义来决定的,前面提到这一层主要是为了解决某一类的分析问题,也就是面向分析,既然是面向分析,那么一般来讲是多个业务过程,而将多个业务过程融合成一个分析主题,势必会关联很多数据。宽表就是这样来的。在olap分析工具还不是很成熟的时候,仍然建议构建多维宽表,这样可以避免过多的模型间的关联操作。一般用于机器学习的特征宽表存在于这一层。集市层构建的好坏有一个比较好的衡量标准就是是否可以满足超过80%的应用层数据需要,剩下的20%来源于数仓层。
D.应用层,从名字来看,很显然这一层主要是面向应用的,面向应用的特点一般有以下几个特征,灵活多变,简单。灵活多变,也就是说业务需要各种形式或者各种自定义口径的数据,如KV结构的,各种条件来计算的。因此复用性较差,需要根据业务来调整和变更;简单,指的是数据一般是高度汇总的,如报表或者核心KPI指标,应用层的数据一般不建议大范围开放,不然其他用户搜索一个指标的时候,会有很多不同的口径,反而不利于数据使用。
4.有哪些让你眼前一亮的数仓设计方法?
数仓设计是有别于传统的业务系统的三范式设计方法的。这里暂时不讨论Inmon和Kimball两位大神设计理念的异同,只从实际工作中来讲。
a. 针对主数据,核心维度,是用缓慢变化维中的哪种设计方法。 请避免使用拉链表,建议改成全量快照表,主要原因在于很多时候需要回刷历史数据。
b. 如何规避上游模型完成过晚问题? 如果对数据准确度要求没有特别高,请使用T-2分区数据 如果数据准确度较高,请先建一张未来分区的全量快照表(如3000-12-31),下游应用直接定点依赖该表。这样的好处在于如果到点,当天的数据已经跑完,则用当前分区数据,反之用T-2数据。
c. 维度过多,算不出来 用好 grouping sets。多维分析的基础,极大的节省olap工具的算力
d.数据变化过快 用好复杂结构,尤其是map,尤其是在对大量页面的PV,UV计算中,因为业务发展太快,页面上了一个又一个,其变化速度远大于模型修改的速度,因为要把模型设计的更灵活。
5.数仓设计的关键点有哪些?
a.熟练掌握列转行和行转列,不展开
b.不是宽表越宽越好,仍然是看你所分析的领域用到的高度相关的数据是否放在一张表里了。大数据时代性能优化的终极方案就是把数据变小
c.开发脚本过程中,千万不要用select * ,除了开发者或许只有上帝知道*都代表了什么。
d.使用其他人数据前记得看别人的模型主键是什么,是否有重复记录,记住了这一条,可以避免绝大多数的数据倾斜
6. 实时数仓的方向?
实时数仓的应用领域越来越广,但并不是说上了实时数仓就能解决所有问题,很多时候离线数据也很好用,那么是否应该上实时数仓呢? 实时数仓从storm,spark发展到现在的flink,最终的方向仍然是让更多的人掌握这门技术,这样才可以更好的推广应用,对于离线的同学也不要觉得实时很难,目前flink sql 发展的较快,主要就是把实时开发变成离线sql的形式,降低门槛,所以关键还是充分考虑业务诉求。让自己的模型真的有用才是最重要的。