概述
上一篇文章主要介绍了数据中台的原理知识,现在开始介绍数据中台的实现篇章,主要从3个方面来说明,第一个是元数据的管理,第二个是指标的规范的管理,第三个是数据模型的建立。
元数据
在原理篇中,我提到数据中台的构建,需要确保全局指标的业务口径一致,要把原先口径不一致的、重复的指标进行梳理,整合成一个统一的指标字典。而这项工作的前提,是要搞清楚这些指标的业务口径、数据来源和计算逻辑。而这些数据呢都是元数据。你可以认为,如果没有这些元数据,就没法去梳理指标,更谈不上构建一个统一的指标体系。当你看到一个数 700W,如果你不知道这个数对应的指标是每日日活,就没办法理解这个数据的业务含义,也就无法去整合这些数据。所以你必须要掌握元数据的管理,才能构建一个数据中台。
那么问题来了:元数据中心应该包括哪些元数据呢? 什么样的数据是元数据?
元数据分类
结合我的实践经验,我把元数据划为三类:数据字典、数据血缘和数据特征。我们还是通过一个例子来理解这三类元数据。
在这个图中,dwd_trd_order_df 是一张订单交易明细数据,任务 flow_dws_trd_sku_1d 读取这张表,按照 sku 粒度,计算每日 sku 的交易金额和订单数量,输出轻度汇总表 dws_trd_sku_1d。数据字典描述的是数据的结构信息,我们以 dws_trd_sku_1d 为例,数据字典包括:
数据血缘是指一个表是直接通过哪些表加工而来,在上面的例子中,dws_trd_sku_1d 是通过 dwd_trd_order_df 的数据计算而来,所以,dwd_trd_order_df 是 dws_trd_sku_1d 的上游表。数据血缘一般会帮我们做影响分析和故障溯源。比如说有一天,你的老板看到某个指标的数据违反常识,让你去排查这个指标计算是否正确,你首先需要找到这个指标所在的表,然后顺着这个表的上游表逐个去排查校验数据,才能找到异常数据的根源。而数据特征主要是指数据的属性信息,我们以 dws_trd_sku_1d 为例:
通过这个例子,你了解了元数据了吗? 不过元数据的种类非常多,为了管理这些元数据,你必须要构建一个元数据中心。那么接下来,我们就来看看如何搭建一个元数据中心,打通企业的元数据。
业界元数据中心产品
我做系统设计这么些年,一直有一个习惯,是先看看业界的产品都是怎么设计的,避免关门造车。业界的比较有影响力的产品:
开源的有 Netflix 的 Metacat、Apache Atlas;
商业化的产品有 Cloudera Navigator。
我今天重点想带你了解 Metacat 和 Atlas 这两款产品,一个擅长于管理数据字典,一个擅长于管理数据血缘,通过了解这两款产品,你更能深入的理解元数据中心应该如何设计。
Metacat 多数据源集成型架构设计关于Metacat,你可以在 GitHub 上找到相关介绍,所以关于这个项目的背景和功能特性,我就不再多讲,我只想强调一个点,就是它多数据源的可扩展架构设计,因为这个点对于数据字典的管理,真的太重要!
在一般的公司中,数据源类型非常多是很常见的现象,包括 Hive、MySQL、Oracle、Greenplum 等等。支持不同数据源,建立一个可扩展的、统一的元数据层是非常重要的,否则你的元数据是缺失的。从上面 Metacat 的架构图中,你可以看到,Metacat 的设计非常巧妙,它并没有单独再保存一份元数据,而是采取直连数据源拉的方式,一方面它不存在保存两份元数据一致性的问题,另一方面,这种架构设计很轻量化,每个数据源只要实现一个连接实现类即可,扩展成本很低,我把这种设计叫做集成型设计。我认为这种设计方式对于希望构建元数据中心的企业,是非常有借鉴意义的。
Apache Atlas 实时数据血缘采集同样,关于Apache Atlas的背景和功能,我也不多说,只是想强调 Atlas 实时数据血缘采集的架构设计,因为它为解决血缘采集的准确性和时效性难题提供了很多的解决思路。血缘采集,一般可以通过三种方式:
通过静态解析 SQL,获得输入表和输出表;
通过实时抓取正在执行的 SQL,解析执行计划,获取输入表和输出表;
通过任务日志解析的方式,获取执行后的 SQL 输入表和输出表。
第一种方式,面临准确性的问题,因为任务没有执行,这个 SQL 对不对都是一个问题。第三种方式,血缘虽然是执行后产生的,可以确保是准确的,但是时效性比较差,通常要分析大量的任务日志数据。所以第二种方式,我认为是比较理想的实现方式,而 Atlas 就是这种实现。
对于 Hive 计算引擎,Atlas 通过 Hook 方式,实时地捕捉任务执行计划,获取输入表和输出表,推送给 Kafka,由一个 Ingest 模块负责将血缘写入 JanusGraph 图数据库中。然后通过 API 的方式,基于图查询引擎,获取血缘关系。对于 Spark,Atlas 提供了 Listener 的实现方式,此外 Sqoop、Flink 也有对应的实现方式。这两款产品在设计网易元数据中心时,给了很多灵感,下面我就带你了解一下其他元数据中心的设计,以便你掌握一个元数据中心在设计时应该考虑哪些点。
我设定了元数据中心必须实现的 5 个关键目标:
其一,多业务线、多租户支持。电商、音乐都是不同的业务线,同一个业务线内,也分为算法、数仓、风控等多个租户,所以元数据中心必须支持多业务线、多租户。
其二,多数据源的支持。元数据中心必须要能够支持不同类型的数据源(比如 MySQL、Hive、Kudu 等),同时还要支持相同数据源的多个集群。为了规范化管理,还需要考虑将半结构化的 KV 也纳入元数据中心的管理(比如 Kafka、Redis、HBase 等)。这些系统本身并没有表结构元数据,所以需要能够在元数据中心里定义 Kafka 每个 Topic 的每条记录 JSON 中的格式,每个字段代表什么含义。
其三,数据血缘。元数据中心需要支持数据血缘的实时采集和高性能的查询。同时,还必须支持字段级别的血缘。什么是字段级别的血缘,我们来举个例子。
1 insert overwrite table t2 select classid, count(userid) from t1 groupby classid;
t2 表是由 t1 表的数据计算来的,所以 t2 和 t1 是表血缘上下游关系,t2 的 classid 字段是由 t1 的 classid 字段产生的,count 字段是由 userid 经过按照 classid 字段聚合计算得到的,所以 t2 表的 classid 与 t1 的 classid 存在字段血缘,t2 表的 count 分别与 t1 表的 classid 和 userid 存在血缘关系。
字段血缘在做溯源的时候非常有用,因为大数据加工链路的下游是集市层,为了方便使用者使用,一般都是一些很宽的表(列很多的表,避免 Join 带来的性能损耗),这个表的上游可能是有几十个表产生的,如果不通过字段血缘限定溯源范围,就会导致搜索范围变得很大,无法快速地精准定位到有问题的表。另外,数据血缘还必须要支持生命周期管理,已经下线的任务应该立即清理血缘,血缘要保留一段时间,如果没有继续被调度,过期的血缘关系应该予以清理。
其四,与大数据平台集成。元数据中心需要与 Ranger 集成,实现基于 tag 的权限管理方式。在元数据中心中可以为表定义一组标签,Ranger 可以基于这个标签,对拥有某一个标签的一组表按照相同的权限授权。这种方式大幅提高了权限管理的效率。比如,对于会员、交易、毛利、成本,可以设定表的敏感等级,然后根据敏感等级,设定不同的人有权限查看。另外,元数据中心作为基础元数据服务,包括自助取数分析系统,数据传输系统,数据服务,都应该基于元数据中心提供的统一接口获取元数据。
其五,数据标签。元数据中心必须要支持对表和表中的字段打标签,通过丰富的不同类型的标签,可以完善数据中台数据的特征,比如指标可以作为一种类型的标签打在表上,主题域、分层信息都可以作为不同类型的标签关联到表。
基于这 5 个因素的考虑,我们设计了元数据中心。
这个图按照功能模块分为数据血缘、数据字典和数据特征。数据血缘由采集端、消息中间件、消费端以及血缘清理模块组成,基于 Hive Hook,Spark Listener,Flink Hook ,可以获取任务执行时输入表和输出表,推送给统一的消息中间件(Kafka),然后消费端负责将血缘关系沉淀到图数据库中。图数据库选择 Neo4j,主要考虑是性能快、部署轻量化、依赖模块少,当然,开源的 Neo4j 没有高可用方案,并且不支持水平扩展,但是因为单个业务活跃的表规模基本也就在几万的规模,所以单机也够用,高可用可以通过双写的方式实现。血缘还有一个清理的模块,主要负责定时清理过期的血缘,一般我们把血缘的生命周期设置为 7 天。数据字典部分,我们参考了 Metacat 实现,我们由一个统一的 Connector Mananger 负责管理到各个数据源的连接。对于 Hive、MySQL,元数据中心并不会保存系统元数据,而是直接连数据源实时获取。对于 Kafka、HBase、Redis 等 KV,我们在元数据中心里内置了一个元数据管理模块,可以在这个模块中定义 Value 的 schema 信息。数据特征主要是标签的管理以及数据的访问热度信息。元数据中心内置了不同类型的标签,同时允许用户自定义扩展标签类型。指标、分层信息、主题域信息都是以标签的形式存储在元数据中心的系统库里,同时元数据中心允许用户基于标签类型和标签搜索表和字段。元数据中心统一对外提供了 API 访问接口,数据传输、数据地图、数据服务等其他的子系统都可以通过 API 接口获取元数据。另外 Ranger 可以基于元数据中心提供的 API 接口,获取标签对应的表,然后根据标签更新表对应的权限,实现基于标签的权限控制。元数据中心构建好以后,你肯定会问,这个元数据中心没有界面吗?它长什么样子?用户咋使用这个元数据中心? 别急,我们接着往下看。
数据地图:元数据中心的界面
数据地图是基于元数据中心构建的一站式企业数据资产目录,可以看作是元数据中心的界面。数据开发、分析师、数据运营、算法工程师可以在数据地图上完成数据的检索,解决了“不知道有哪些数据?”“到哪里找数据?”“如何准确的理解数据”的难题。
数据地图提供了多维度的检索功能,使用者可以按照表名、列名、注释、主题域、分层、指标进行检索,结果按照匹配相关度进行排序。考虑到数据中台中有一些表是数仓维护的表,有一些表数仓已经不再维护,在结果排序的时候,增加了数仓维护的表优先展示的规则。同时数据地图还提供了按照主题域、业务过程导览,可以帮助使用者快速了解当前有哪些表可以使用。
当使用者定位到某一个表打开时,会进入详情页,详情页中会展示表的基础信息,字段信息、分区信息、产出信息以及数据血缘。数据血缘可以帮助使用者了解这个表的来源和去向,这个表可能影响的下游应用和报表,这个表的数据来源。
数据地图同时还提供了数据预览的功能,考虑到安全性因素,只允许预览 10 条数据,用于判断数据是否符合使用者的预期。数据地图提供的收藏功能, 方便使用者快速找到自己经常使用的表。当数据开发、分析师、数据运营找到自己需要的表时,在数据地图上可以直接发起申请对该表的权限申请。数据地图对于提高数据发现的效率,实现非技术人员自助取数有重要作用。经过我的实践,数据地图是数据中台中使用频率最高的一个工具产品,在网易,每天都有 500 以上人在使用数据地图查找数据。
数据指标规范
元数据在指标管理、模型设计、数据质量和成本治理四个领域都发挥着作用,而这些领域构成了数据中台 OneData 数据体系。从今天开始,我将带你逐一了解元数据在上述领域的应用,首先是指标管理。指标是一种特定类型的元数据,公司的运营会围绕它进行工作,可以说,它是业务和数据的交汇点。指标数据能不能用,会影响他们的日常工作。来看一件我身边发生的事儿。在电商业务中,新用户销售额是考核市场活动拉新效果的重要指标。马漂亮(化名)是市场部门的数据分析师,某一天,她要给 CEO 提供一份数据报告,报告中有一项指标是“新用户销售额”。孙美丽(化名)是会员中心的运营,她每天都会给 CEO 提供每日的新用户销售额数据。结果有一天,CEO 看了这两份报告后发现,同一日的新用户销售额数值相差很大,他判断数据出了问题,责令两个部门的负责人进行排查。排查后发现,市场部门对新用户口径的定义和会员中心不一样:
市场部门认定新用户是首次下单并完成支付的用户;
会员中心认定新用户是当日新注册用户。
也就是说,市场部门认定的新用户中,可能有之前注册但是没有下过单的客户;而会员中心只包括当日注册并完成下单支付的用户。其实,在日常工作中还有很多类似的问题。造成上述问题的根源是因为指标口径不一致,而你要构建全局一致的指标口径,输出企业的指标字典。
指标混乱现状
同名不同径,同径不同名。口径不清晰,口径有错误。命名难理解,计算不易懂。来源不清晰,同部不同径。
第一,相同指标名称,口径定义不同。我开篇说的就是这个问题,不同的部门对相同的“新用户销售额”,因为口径定义的差别,导致指标数值的不一致。而这种情况是指标管理中最容易出现的情况。口径不一致,数据也就没办法横向对比,失去了数据辅助商业决策的意义。
第二,相同口径,指标名称不一样。这种情况与上面相反,比如发放优惠券是电商常见的促销手段,现在你有两个数据产品:一个是经营大脑,主要展示的是企业日常经营活动健康度的核心指标,它有一个指标叫“优惠券抵扣金额”;一个是市场 360,主要是展示市场活动效果衡量的指标,它也有一个指标叫“优惠券消耗金额”。其实,两者的口径定义并没有区别,但是指标名称不同,这会让使用指标的人疑惑,是不是同一个指标,计算逻辑是否一致?数据是否可以横向对比?
第三,不同限定词,描述相同事实过程的两个指标,相同事实部分口径不一致。
第四,指标口径描述不清晰。在梳理过程中,我们还发现,有些报表上的指标口径描述的比较笼统。比如“关单金额”,口径描述“关闭订单的金额”。不同人的理解可能不一样,有的人会认为是支付成功后关闭订单;也有可能是支付完成前,取消订单。描述不清晰,就会让人们对数据的理解产生歧义。
第五,指标口径描述错误。在流量分析数据产品中,有“7 日 uv”这个指标,口径的定义是 7 日内日均 uv。根据口径描述的计算逻辑,应该是最近 7 日,每日 uv 相加除以 7 取平均值。显然,这个定义在业务场景中是有问题的,正确的 7 日 uv 的口径定义应该是 7 日内有登录过,去重的用户数。
第六,指标命名难于理解。我们在梳理促销业务过程的指标时,有一个数据产品的指标名称是“ROI”,口径定义优惠券销售额 / 优惠券成本。ROI 其实是投资回报率的简称,在电商业务场景中,除了优惠劵,商品降价促销都可以计算 ROI,所以比较好的命名应该是(商品|类目|通用)优惠劵 ROI。所以,指标命名不规范的话,从指标名称中很难看出指标描述的业务过程。
最后,指标数据来源和计算逻辑不清晰。如果指标数据来源不清楚,一旦这个指标数据异常,就很难去做溯源。另外,有些指标的计算逻辑比较复杂,仅仅凭借业务口径一段描述,使用指标的人还是无法理解这个指标的计算逻辑,这个时候就需要有一些伪码或者 SQL 描述。
如何规范化定义指标
那么如果你面临这些问题,该如何规范化定义指标呢?我提供给你一些经验,希望你能从中学习到如何高效、规范化的管理指标。
为了提高指标管理的效率,你需要按照业务线、主题域和业务过程三级目录方式管理指标(业务线是顶级目录)。电商、游戏、音乐、传媒、教育都是不同的业务线。在业务线之下,是主题域,指标中的主题域与数仓中的概念是一致的,划分标准最好是跟数仓保持一致(数仓主题域的划分,我会在 06 讲详细讲述)。在主题域下面还有细分的业务过程,比如对于交易域,细分的业务过程有加入购物车、下单、支付。
其次,拆分原子指标和派生指标。为了解决前面提到的,“黑卡购买用户数”和“非会员购买用户数”,这两个指标对购买用户数口径定义不一致的问题,我们需要引入原子指标和派生指标的管理方式。那么什么是原子指标,什么是派生指标呢?统计周期、统计粒度、业务限定、原子指标,组成派生指标,所以原子指标可以定义为不能够按照上述规则进一步拆分的指标。
在例子中,你可以这样理解:购买用户数是原子指标,原子指标的口径定义是“计算周期内去重的,下单并且支付成功的用户数量,包括关单”;黑卡会员和非会员都可以认定为业务限定词;统计粒度是商品粒度的;统计周期是 30 天。
这样 30 天内,商品维度的黑卡会员购买用户数和 30 天内商品维度的非会员购买用户数就作为两个派生指标存在,但是他们继承自同一个原子指标。
除此之外,还需要指标命名规范。指标命名规范要遵循两个基本的原则:易懂,就是看到指标的名称,就可以基本判断这个指标归属于哪个业务过程;统一,就是要确保派生指标和它继承的原子指标命名是一致的。除此之外,指标应该有指标名称和指标标识(或者叫英文名)。
对于原子指标,指标名称适合用“动作 + 度量”的命名方式(比如注册用户数、购买用户数),标识的命名用英文简写或者汉语拼音缩写比较好。对于派生指标,指标名称应该严格遵循“时间周期 + 统计粒度 + 修饰词 + 原子指标”的命名方式,标识命名要用“修饰词 _ 原子指标 _ 时间周期”的方式。
第四,关联的应用和可分析维度。对于使用指标的人(运营、分析师)了解了这个指标的口径定义之后,下一步就是要看指标的数值。所以,在全局的指标字典中,还应该有指标被哪些应用使用,这样方便去对应的数据产品或者报表上查看指标的数值。除此之外,还应该有指标的可分析维度,方便分析师从不同的维度分析指标的变化趋势。
最后一个是分等级管理。那这么多指标,数据中台管的过来么?是的,确实管不过来,因为不仅仅是数据中台会产出一些公共核心指标,业务部门也会创建一些专属业务部门内的指标。那面对这么多指标,如何管理呢?以我的经验,你可以按照以下原则区分等级,来管理指标。一级指标:数据中台直接产出,核心指标(提供给公司高层看的)、原子指标以及跨部门的派生指标。二级指标:基于中台提供的原子指标,业务部门创建的派生指标。不同等级的指标意味着管理方式不同:一级指标,要确保指标按时、保证质量产出,指标创建由中台负责;二级指标,允许业务方自己创建,中台不承诺指标的产出时间和质量。现在你了解如何管理指标了吗? 我建议你在学完这部分知识以后,结合自己所在的业务,找一些指标,试着按照上面的方法实践一下,这样掌握得会加更深刻。
指标系统
在了解如何管理指标之后,我们还需要一款好用的工具,帮助我们落实管理方法。我观察到,很多公司喜欢用 Excel 管理指标,觉得 Excel 上手容易,编辑比较方便。在我看来,Excel 并不是一个适合指标管理的工具,有这样几个原因:难于共享;缺少权限控制;无法动态更新;指标无法跟数仓的模型动态关联。所以,我们需要一个面向指标的管理系统。
指标系统是基于元数据中心构建的一个指标管理工具,它从元数据中心自动同步数仓的主题域和业务过程,按照规范化定义创建指标。新创建的指标同时会以特定类型的标签,下沉到元数据中心对应的表和字段上,这样在数据地图上就可以搜索到表关联的指标。
既然指标系统能够实现指标的规范化定义,帮你解决“如何系统化、规范化定义指标”的问题,那接下来我们的重点就是如何基于指标系统构建全局的指标字典,因为这是指标治理的最终结果。
基于指标系统构建全局的指标字典指标治理的最终结果,就是要形成一个全局业务口径一致的指标字典。让使用指标的人,可以通过指标字典,快速了解指标的业务含义和计算过程,不会对指标口径产生歧义。数据中台团队必须要有一个专门负责指标管理的人或者小组(一般不超过 3 个人),最好是数据产品经理来负责,如果你的公司没有这个职位,也可以让分析师承担(前提是分析师必须属于中台团队)。
构建全局的指标字典分为两个场景:一个是面对一个新的指标需求,如何基于指标系统完成指标开发流程;另外一个是面对已经存在的,混乱的指标现状,如何进行全局梳理。
我们先看第一个场景。
这个图详细地描述了新建指标的流程,流程中参与的各个角色。我在这里想强调几点:
指标需求评审,需要需求方、数据开发、应用开发都参加。评审首先要确认这是不是一个新的指标,并明确它是原子指标还是派生指标。评审的目的就是要大家达成一致。
评审的结果一种是不需要开发,是一个已经存在的指标,直接可以通过设计逻辑模型(具体我会在数据服务章节讲),发布接口,获取数据。第二种就是需要开发。前者交付时间短,后者需要排期,交付时间长。
上面我提到指标有一级和二级之分,这个流程适用于一级指标,对于二级指标,可以不需要评审,当然开发也是由业务方开发和发布上线。
接下来,我们来看第二个场景。除了新建指标的流程,对于很多公司,已经有一定的大数据业务,但是还不能算是一个中台,那这部分公司该如何进行一次全局的指标梳理呢?我认为应该有以下几个步骤:成立以数据产品或者分析师为核心的 1~3 人的工作小组,专门负责指标的全局梳理;制定指标梳理计划,明确指标梳理目标,覆盖多少个业务线,与业务方共同制定时间计划;对于每一个业务线,需要对还在使用的数据报表、数据产品进行盘点,这里顺便可以把没用的报表和数据产品应该下线;对于每一个报表和数据产品中涉及的指标,按照以下格式进行收集;
对于收集的指标,明确业务口径,对于口径相同的,应该去除重复,关联的应用应该合并,此时以我的经验,可以过滤掉相当一部分;根据指标业务口径,明确指标所属的主题域、业务过程;区分指标类型,对于派生指标,要明确指标的统计粒度、修饰词、时间周期以及关联的原子指标;按照指标系统对指标的规范化定义,把整理好的指标录入指标系统。通过全局的梳理和新建指标流程的管控,你就可以构建一个全局一致的指标字典了。
数据模型
我带你了解了数据中台如何管理指标,如果我们把指标比喻成一棵树上的果实,那模型就是这棵大树的躯干,想让果实结得好,必须让树干变得粗壮。
先来看一幕真实的场景。大多数公司的分析师会结合业务做一些数据分析(需要用到大量的数据),通过报表的方式服务于业务部门的运营。但是在数据中台构建之前,分析师经常发现自己没有可以复用的数据,不得不使用原始数据进行清洗、加工、计算指标。由于他们大多是非技术专业出身,写的 SQL 质量比较差,我甚至见过 5 层以上的嵌套。这种 SQL 对资源消耗非常大,会造成队列阻塞,影响其他数仓任务,会引起数据开发的不满。数据开发会要求收回分析师的原始数据读取权限,分析师又会抱怨数仓数据不完善,要啥没啥,一个需求经常要等一周甚至半个月。分析师与数据开发的矛盾从此开始。这个矛盾的根源在于数据模型无法复用,数据开发是烟囱式的,每次遇到新的需求,都从原始数据重新计算,自然耗时。而要解决这个矛盾,就要搞清楚我们的数据模型应该设计成什么样子。
什么才是一个好的数据模型设计?
来看一组数据,这两个表格是基于元数据中心提供的血缘信息,分别对大数据平台上运行的任务和分析查询(Ad-hoc)进行的统计。
下图是数仓分层架构图,方便你回忆数据模型分层的设计架构:
我们首先来看表 1。表 1 中有 2547 张未识别分层的表,占总表 6049 的 40%,它们基本没办法复用。 重点是在已识别分层的读表任务中,ODS:DWD:DWS:ADS 的读取任务分别是 1072:545:187:433,直接读取 ODS 层任务占这四层任务总和的 47.9%,这说明有大量任务都是基于原始数据加工,中间模型复用性很差。我们再来看看表 2,在已识别的分层的查询中,ODS:DWD:DWS:ADS 的命中的查询分别是 892:1008:152:305,有 37.8% 的查询直接命中 ODS 层原始数据,说明 DWD、DWS、ADS 层数据建设缺失严重。尤其是 ADS 和 DWS,查询越底层的表,就会导致查询扫描的数据量会越大,查询时间会越长,查询的资源消耗也越大,使用数据的人满意度会低。最后,我们进一步对 ODS 层被读取的 704 张表进行分解,发现有 382 张表的下游产出是 DWS,ADS,尤其是 ADS 达到了 323 张表,占 ODS 层表的比例 45.8%,说明有大量 ODS 层表被进行物理深加工。通过上面的分析,我们似乎已经找到了一个理想的数仓模型设计应该具备的因素,那就是“数据模型可复用,完善且规范”。
如何衡量完善度
DWD 层完善度:衡量 DWD 层是否完善,最好看 ODS 层有多少表被 DWS/ADS/DM 层引用。因为 DWD 以上的层引用的越多,就说明越多的任务是基于原始数据进行深度聚合计算的,明细数据没有积累,无法被复用,数据清洗、格式化、集成存在重复开发。因此,我提出用跨层引用率指标衡量 DWD 的完善度。跨层引用率:ODS 层直接被 DWS/ADS/DM 层引用的表,占所有 ODS 层表(仅统计活跃表)比例。跨层引用率越低越好,在数据中台模型设计规范中,我们要求不允许出现跨层引用,ODS 层数据只能被 DWD 引用。
DWS/ADS/DM 层完善度:考核汇总数据的完善度,我认为主要看汇总数据能直接满足多少查询需求(也就是用汇总层数据的查询比例衡量)。如果汇总数据无法满足需求,使用数据的人就必须使用明细数据,甚至是原始数据。汇总数据查询比例:DWS/ADS/DM 层的查询占所有查询的比例。你要明确的是,这个跟跨层引用率不同,汇总查询比例不可能做到 100%,但值越高,说明上层的数据建设越完善,对于使用数据的人来说,查询速度和成本会减少,用起来会更爽。
如何衡量复用度
数据中台模型设计的核心是追求模型的复用和共享,通过元数据中心的数据血缘图,我们可以看到,一个比较差的模型设计,自下而上是一条线。而一个理想的模型设计,它应该是交织的发散型结构。
我提出用模型引用系数作为指标,衡量数据中台模型设计的复用度。引用系数越高,说明数仓的复用性越好。模型引用系数:一个模型被读取,直接产出下游模型的平均数量。比如一张 DWD 层表被 5 张 DWS 层表引用,这张 DWD 层表的引用系数就是 5,如果把所有 DWD 层表(有下游表的)引用系数取平均值,则为 DWD 层表平均模型引用系数,一般低于 2 比较差,3 以上相对比较好(经验值)。
如何衡量规范度
表 1 中,超过 40% 的表都没有分层信息,在模型设计层面,这显然是不规范的。除了看这个表有没有分层,还要看它有没有归属到主题域(例如交易域)如果没有归属主题域,就很难找到这张表,也无法复用。其次,你要看表的命名。拿 stock 这个命名为例,当你看到这个表时,知道它是哪个主题域、业务过程?是全量数据的表,还是每天的增量数据?总的来说,通过这个表名获取的信息太有限了。一个规范的表命名应该包括主题域、分层、表是全量快照,还是增量等信息。除此之外,如果在表 A 中用户 ID 的命名是 UserID,在表 B 中用户 ID 命名是 ID,就会对使用者造成困扰,这到底是不是一个东西。所以我们要求相同的字段在不同的模型中,它的命名必须是一致的。
讲了这么多,你要如何吸收经验呢?在这里,我给你几点建议。
你可以拿着这些指标去评估一下,自己的数仓现状如何。
然后制订一些针对性的改进计划,比如把这些不规范命名的表消灭掉,把主题域覆盖的表比例提高到 90% 以上。
在尝试完一段时间的模型重构和优化后,再拿着这些指标去测一测是不是真的变好了。我见过很多数据开发在向上级汇报工作时,喜欢用重构了多少模型说明工作成果,很多老大会想,这些重构到底对数据建设有多少帮助?有没有一些量化的指标可以衡量?我想有上面的知识,你可以应对这个问题了。
现在你知道什么是好的数仓设计了,可目前已经存在了大量烟囱式开发,具体怎么做才能让它变成一个数据中台呢?
如何从烟囱式的小数仓到共享的数据中台
建设数据中台本质就是构建企业的公共数据层,把原先分散的、烟囱式的、杂乱的小数仓,合并成一个可共享、可复用的数据中台。结合我的实践经验,我给你几点建议。
第一,接管 ODS 层,控制源头。ODS 是业务数据进入数据中台的第一站,是所有数据加工的源头,控制住源头,才能从根本上防止一个重复的数据体系的出现。数据中台团队必须明确职责,全面接管 ODS 层数据,从业务系统的源数据库权限入手,确保数据从业务系统产生后进入数据仓库时,只能在数据中台保持一份。这个可以跟业务系统数据库管理者达成一致,只有中台团队的账号才能同步数据。ODS 层表的数据必须和数据源的表结构、表记录数一致,高度无损,对于 ODS 层表的命名采用 ODS_ 业务系统数据库名 _ 业务系统数据库表名方式,比如 ods_warehous_stock,warehous 是业务系统数据库名,stock 是该库下面的表名。
第二,划分主题域,构建总线矩阵。主题域是业务过程的抽象集合。可能这么讲,稍微有点儿抽象,但其实业务过程就是企业经营过程中一个个不可拆分的行为事件,比如仓储管理里面有入库、出库、发货、签收,都是业务过程,抽象出来的主题域就是仓储域。
主题域划分要尽量涵盖所有业务需求,保持相对稳定性,还具备一定的扩展性(新加入一个主题域,不影响已经划分的主题域的表)。主题域划分好以后,就要开始构建总线矩阵,明确每个主题域下的业务过程有哪些分析维度,举个例子:
第三,构建一致性维度。售后团队的投诉工单数量有针对地区的分析维度,而配送团队的配送延迟也有针对地区的分析维度,你想分析因为配送延迟导致的投诉增加,但是两个地区的分析维度包含内容不一致,最终会导致一些地区没办法分析。所以我们构建全局一致性的维表,确保维表只存一份。维度统一的最大的难题在于维度属性(如果维度是商品,那么商品类别、商品品牌、商品尺寸等商品的属性,我们称为维度属性)的整合。是不是所有维度属性都要整合到一个大的维表中,也不见得,我给你几个建议。
公共维度属性与特有维度属性拆成两个维表。在自营平台中,通常也会有一些第三方的商家入驻,但是数量很少。大部分商品其实都没有店铺的属性,这种情况,就不建议将店铺和商品的其他维度属性,比如商品类别、品牌设计成一个维表。
产出时间相差较大的维度属性拆分单独的维表,比如有些维度属性产出时间在凌晨 2 点,有些维度属性产出时间在凌晨 6 点,那 2 点和 6 点的就可以拆成两个维表,确保核心维表尽早产出。
出于维表稳定性产出的考虑,你可以将更新频繁的和变化缓慢的进行拆分,访问频繁的和访问较少的维表进行拆分。对于维表的规范化命名,建议你用“DIM_ 主题域 _ 描述 _ 分表规则”方式。分表你可以这样理解:一个表存储几千亿行记录实在是太大了,所以需要把一个表切割成很多小的分区,每天或者每周,随着任务被调度,会生成一个分区。我提供给你一个常见的分区规则(这个规则你在用的时候,查阅就可以了)。
第四,事实表整合。我觉得事实表整合遵循的最基本的一个原则是,统计粒度必须保持一致,不同统计粒度的数据不能出现在同一个事实表中。来看一个例子:
在数据中台构建前,供应链部门、仓储部门和市场部门都有一些重复的事实表,我们需要将这些重复的内容进行去除,按照交易域和仓储域,主题域的方式进行整合。
对于仓储部门和供应链部门都有的库存明细表,因为仓储部门的统计粒度是商品加仓库,而供应链部门的只有商品,所以原则上两个表是不能合并,而是应该独立存在。
对于市场部门和供应链部门的两张下单明细表,因为统计粒度都是订单级别,都归属于交易域下的下单业务过程,所以可以合并为一张事实表。除此之外,还应该考虑将不全的数据补齐。对于 ODS 层直接被引用产出 DWS/ADS/DM 层的任务,通过血缘,找到任务清单,逐个进行拆解。没有 ODS 对应的 DWD 的,应该生成 DWD 表,对于已经存在的,应该迁移任务,使用 DWD 层表。
DWD/DWS/ADS/DM 的命名规则适合采用“[层次][主题][子主题][内容描述][分表规则]”的命名方式。
第五,模型开发。模型设计完成后,就进入模型开发阶段,我想提几个你需要注意的点:
所有任务都必须严格配置任务依赖,如果没有配置任务依赖,会导致前一个任务没有正常产出数据的情况下,后一个任务被调度起来,基于错误的数据空跑,浪费资源,同时增加了排查故障的复杂度;
任务中创建的临时表,在任务结束前应该删除,如果不删除,会发现有大量的临时表存在,占用空间;
任务名称最好跟表名一致,方便查找和关联;
生命周期的管理,对于 ODS 和 DWD,一般尽可能保留所有历史数据,对于DWS/ADS/DM 需要设置生命周期,7~30 天不等;
DWD 层表宜采用压缩的方式存储,可用 lzo 压缩。
第六,应用迁移。最后一步就是应用的迁移,这个过程的核心是要注意数据的比对,确保数据的完全一致,然后进行应用迁移,删除老的数据表。总的来说,建设数据中台不是一口气就能吃成一个胖子,它的建设往往是滚雪球的方式,随着一个个应用的迁移,中台的数据也越来越丰满,发挥的价值也越来越大。
总结
以后关于数据中台系列的总结大部分来自Geek Time的课件,大家可以自行关键字搜索。