通常数据仓库的数据来自各个业务应用系统。业务系统中的数据形式多种多样,可能是 Oracle、MySQL、SQL Server 等关系数据库里的结构化数据,可能是文本、CSV 等平面文件或 Word、Excel 文档中的数据,还可能是 HTML、XML 等自描 述的半结构化数据。这些业务数据经过一系列的数据抽取、转换、清洗,最终以一种统一的格式装载进数据仓库。数据仓库里的数据作为分析用的数据源,提供给后面的即席查询、 分析系统、数据集市、报表系统、数据挖掘系统等。
这时我们就想了,为什么不能把业务系统的数据直接拿来供即席查询、分析系统、报表系统等使用呢,为什么要经过数据仓库这一步?实际上在数仓出现之前,确实是这么做的,但是有很多数据分析的先驱者当时已经发现,简单的直接访问方式很难良好工作,这样做的失败案例数不胜数。下面列举一些直接访问业务系统无法工作的原因:
尽管需要增加软硬件的投入,但建立独立数据仓库与直接访问业务数据相比,无论是成本还是带来的好处,这样做都是值得的。随着处理器和存储成本的逐年降低,数据仓库方案的优势更加明显,在经济上也更具可行性。
英文名称为 Data Warehouse,可简写为 DW 或 DWH。数据仓库的目的是构建面向分析的集成化数据环境,为企业提供决策支持(Decision Support)。它出于分析性报告和决策支持目的而创建。
数据仓库本身并不“生产”任何数据,同时自身也不需要“消费”任何的数据,数据来源于外部,并且开放给外部应用,这也是为什么叫“仓库”,而不叫“工厂”的原因。
数据仓库是面向主题的、集成的、非易失的和时变的数据集合,用以支持管理决策。
面向主题:
传统数据库中,最大的特点是面向应用进行数据的组织,各个业务系统可能是相互分离的。而数据仓库则是面向主题的。主题是一个抽象的概念,是较高层次上企业信息系统中的数据综合、归类并进行分析利用的抽象。在逻辑意义上,它是对应企业中某一宏观分析领域所涉及的分析对象。
集成性:
通过对分散、独立、异构的数据库数据进行抽取、清理、转换和汇总便得到了数据仓库的数据,这样保证了数据仓库内的数据关于整个企业的一致性。
数据仓库中的综合数据不能从原有的数据库系统直接得到。因此在数据进入数据仓库之前,必然要经过统一与综合,这一步是数据仓库建设中最关键、最复杂的一步,所要完成的工作有:
下图说明一个保险公司综合数据的简单处理过程,其中数据仓库中与“保险” 主题有关的数据来自于多个不同的操作型系统。这些系统内部数据的命名可能不同,数据格式也可能不同。把不同来源的数据存储到数据仓库之前,需要去除这些不一致。
非易失性:
数据仓库的数据反映的是一段相当长的时间内历史数据的内容,是不同时点的数据库快照的集合,以及基于这些快照进行统计、综合和重组的导出数据。
数据非易失性主要是针对应用而言。数据仓库的用户对数据的操作大多是数据查询或比较复杂的挖掘,一旦数据进入数据仓库以后,一般情况下被较长时间保留。数据仓库中一般有大量的查询操作,但修改和删除操作很少。因此,数据经加工和集成进入数据仓库后是极少更新的,通常只需要定期的加载和更新。
时变性:
数据仓库包含各种粒度的历史数据。数据仓库中的数据可能与某个特定日期、星期、月份、季度或者年份有关。数据仓库的目的是通过分析企业过去一段时间业务的经营状况,挖掘其中隐藏的模式。虽然数据仓库的用户不能修改数据,但并不是说数据仓库的数据是永远不变的。分析的结果只能反映过去的情况,当业务变化后,挖掘出的模式会失去时效性。因此数据仓库的数据需要更新,以适应决策的需要。从这个角度讲,数据仓库建设是一个项目,更是一个过程。数据仓库的数据随时间的变化表现在以下几个方面:
上图中显示的整个数据仓库环境包括操作型系统和数据仓库系统两大部分。操作型系统的数据由各种形式的业务数据组成,这些数据经过抽取、转换和装载(ETL)过程进入数据仓库系统。
任何事物都是随着时间的演进变得越来越完善,当然也是越来越复杂,数仓也不例外。在数据仓库技术演化过程中,产生了几种主要的架构方法,包括数据集市架构、Inmon企业信息工厂架构、Kimball数据仓库架构、混合型数据仓库架构。
数据集市是按主题域组织的数据集合,用于支持部门级的决策。有两种类型的数据集市:独立数据集市和从属数据集市。
1) 独立数据集市
独立数据集市集中于部门所关心的单一主题域,数据以部门为基础部署,无须考虑企业级别的信息共享与集成。例如,制造部门、人力资源部门和其他部门都各自有他们自己的数据集市。
优点:因为一个部门的业务相对于整个企业要简单,数据量也小得多,所以部门的独立数据集市具有周期短、见效快的特点。
缺点:
2) 从属数据集市
从属数据集市的数据来源于数据仓库。数据仓库里的数据经过整合、重构、汇总后传递给从属数据集市。
建立从属数据集市的好处主要有:
上图的前两步不过多介绍,直接从第三步开始。
企业级数据仓库:是该架构中的核心组件。正如Inmon数据仓库所定义的,企业级数据仓库是一个细节数据的集成资源库。其中的数据以最低粒度级别被捕获,存储在满足三范式设计的关系数据库中。
部门级数据集市:是面向主题数据的部门级视图,数据从企业级数据仓库获取。数据在进入部门数据集市时可能进行聚合。数据集市使用多维模型设计,用于数据分析。重要的一点是,所有的报表工具、BI工具或其他数据分析应用都从数据集市查询数据,而不是直接查询企业级数据仓库。
对比上一张图可以看到,Kimball与Inmon两种架构的主要区别在于核心数据仓库的设计和建立。
Kimball的数据仓库包含高粒度的企业数据,使用多维模型设计,这也意味着数据仓库由星型模式的维度表和事实表构成。分析系统或报表工具可以直接访问多维数据仓库里的数据。
在此架构中的数据集市也与Inmon中的不同。这里的数据集市是一个逻辑概念,只是多维数据仓库中的主题域划分,并没有自己的物理存储,也可以说是虚拟的数据集市。
所谓的混合型结构,指的是在一个数据仓库环境中,联合使用Inmon和Kimball两种架构。
从架构图可以看到,这种架构将Inmon方法中的数据集市部分替换成了一个多维数据仓库,而数据集市则是多维数据仓库上的逻辑视图。
使用这种架构的好处是:既可以利用规范化设计消除数据冗余,保证数据的粒度足够细;又可以利用多维结构更灵活地在企业级实现报表和分析。
按照数据流入流出的过程,数据仓库架构可分为:源数据、数据仓库、数据应用
数据仓库的数据来源于不同的源数据,并提供多样的数据应用,数据自下而上流入数据仓库后向上层开放应用,而数据仓库只是中间集成化数据管理的一个平台。
源数据:此层数据无任何更改,直接沿用外围系统数据结构和数据,不对外开放;为临时存储层,是接口数据的临时存储区域,为后一步的数据处理做准备。
数据仓库:也称为细节层,DW层的数据应该是一致的、准确的、干净的数据,即对源系统数据进行了清洗(去除了杂质)后的数据。
数据应用:前端应用直接读取的数据源;根据报表、专题分析需求而计算生成的数据。
数据仓库从各数据源获取数据及在数据仓库内的数据转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程,ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。
问题:那么为什么要数据仓库进行分层呢?
实体是指依附的主体,就是我们分析的一个对象,比如我们分析商品的销售情况,如华为手机近半年的销售量是多少,那华为手机就是一个实体;我们分析用户的活跃度,用户就是一个实体。当然实体也可以现实中不存在的,比如虚拟的业务对象,活动,会员等都可看做一个实体。
实体的存在是为了业务分析,作为分析的一个筛选的维度,拥有描述自己的属性,本身具有可分析的价值。
维度就是看待问题的角度,分析业务数据,从什么角度分析,就建立什么样的维度。所以维度就是要对数据进行分析时所用的一个量,比如你要分析产品销售情况,你可以选择按商品类别来进行分析,这就构成一个维度,把所有商品类别集合在一起,就构成了维度表。
度量是业务流程节点上的一个数值。比如销量,价格,成本等等。
事实表中的度量可分为三类:完全可加,半可加,不可加。
粒度就是业务流程中对度量的单位,比如商品是按件记录度量,还是按批记录度量。
在数仓建设中,我们说这是用户粒度的事实表,那么表中每行数据都是一个用户,无重复用户;例如还有销售粒度的表,那么表中每行都是一条销售记录。
选择合适的粒度级别是数据仓库建设好坏的重要关键内容,在设计数据粒度时,通常需重点考虑以下因素:
口径就是取数逻辑(如何取数的),比如要取的数是10岁以下儿童中男孩的平均身高,这就是统计的口径。
指标是口径的衡量值,也就是最后的结果。比如最近七天的订单量,一个促销活动的购买转化率等。
一个指标具体到计算实施,主要有以下几部分组成:
除此之外,指标本身还可以衍生、派生出更多的指标,基于这些特点,可以将指标进行分类:
业务方更关心的指标,是有实际业务含义,可以直接取数据的指标。比如店铺近1天订单支付金额就是一个派生指标,会被直接在产品上展示给商家看。
但是这个指标却不能直接从数仓的统一中间层里取数(因为没有现成的事实字段,数仓提供的一般都是大宽表)。需要有一个桥梁连接数仓中间层和业务方的指标需求,于是便有了派生指标
维度:观察各项指标的角度;
修饰词:维度的一个或某些值,比如维度性别下,男和女就是2种修饰词。
标签是人为设定的、根据业务场景需求,对目标对象运用一定的算法得到的高度精炼的特征标识。可见标签是经过人为再加工后的结果,如网红、白富美、萝莉。对于有歧义的标签,我们内部可进行标签区分,比如:苹果,我们可以定义苹果指的是水果,苹果手机才指的是手机。
由现实中已经存在的属性组成的键,它在业务概念中是唯一的,并具有一定的业务含义,比如商品ID,员工ID。
以数仓角度看,来自于业务系统的标识符就是自然键,比如业务库中员工的编号。
保持永久性不会发生变化。有时也被叫做超自然持久键。比如身份证号属于持久键。
自然键和持久键区别:举个例子就明白了,比如说公司员工离职之后又重新入职,他的自然键也就是员工编号发生了变化,但是他的持久键身份证号是不变的。
就是不具有业务含义的键。代理键有许多其他的称呼:无意义键、整数键、非自然键、人工键、合成键等。
代理键就是简单的以按照顺序序列生产的整数表示。产品行的第1行代理键为1,则下一行的代理键为2,如此进行。代理键的作用仅仅是连接维度表和事实表。
退化维度,就是那些看起来像是事实表的一个维度关键字,但实际上并没有对应的维度表,就是维度属性存储到事实表中,这种存储到事实表中的维度列被称为退化维度。与其他存储在维表中的维度一样,退化维度也可以用来进行事实表的过滤查询、实现聚合操作等。
那么究竟怎么定义退化维度呢?比如说订单id,这种量级很大的维度,没必要用一张维度表来进行存储,而我们进行数据查询或者数据过滤的时候又非常需要,所以这种就冗余在事实表里面,这种就叫退化维度,citycode这种我们也会冗余在事实表里面,但是它有对应的维度表,所以它不是退化维度。
这是在数据分析中常见的概念,下钻可以理解成增加维的层次,从而可以由粗粒度到细粒度来观察数据,比如对产品销售情况分析时,可以沿着时间维从年到月到日更细粒度的观察数据。从年的维度可以下钻到月的维度、日的维度等。
知道了下钻,上卷就容易理解了,它俩是相逆的操作,所以上卷可以理解为删掉维的某些层,由细粒度到粗粒度观察数据的操作或沿着维的层次向上聚合汇总数据。
维度立方体包含了下钻和上卷的所有操作,站在多个维度角度取看待事情,那么就会有不同的结果,所以维度立方体统计可以满足任何维度需求,不过缺点是结果过多,导致程序运行速度大大降低。
数据集市(Data Mart),也叫数据市场,数据集市就是满足特定的部门或者用户的需求,按照多维的方式进行存储,包括定义维度、需要计算的指标、维度的层次等,生成面向决策分析需求的数据立方体。其实就是从数据仓库中抽取出来的一个小合集。
在Kimball维度建模中有维度与事实,在Inmon范式建模中有实体与关系,如果我们分开两种建模方式看这些概念比较容易理解。但是目前也出现了不少混合建模方式,两种建模方式结合起来看,这些概念是不是容易记忆混乱,尤其事实表和实体表,它们之间到底有怎样区别与联系,先看下它们各自概念:
举个例子:
比如说手机商场中有苹果手机,华为手机等各品牌各型号的手机,这些数据可以组成一个手机实体表,但是表中没有可度量的数据。某天苹果手机卖了15台,华为手机卖了20台,这些手机销售数据属于事实,组成一个事实表。这样就可以使用日期维度表和地域维度表对这个事实表进行各种维度分析。
概念不同
指标是用来定义、评价和描述特定事物的一种标准或方式。比如:新增用户数、累计用户数、用户活跃率等是衡量用户发展情况的指标;
标签是人为设定的、根据业务场景需求,对目标对象运用一定的算法得到的高度精炼的特征标识。可见标签是经过人为再加工后的结果,如网红、白富美、萝莉。
构成不同
指标名称是对事物质与量两方面特点的命名;指标取值是指标在具体时间、地域、条件下的数量表现,如人的体重,指标名称是体重,指标的取值就是120斤;
标签名称通常都是形容词或形容词+名词的结构,标签一般是不可量化的,通常是孤立的,除了基础类标签,通过一定算法加工出来的标签一般都没有单位和量纲。如将超过200斤的称为大胖子。
分类不同
对指标的分类:
按照指标计算逻辑,可以将指标分为原子指标、派生指标、衍生指标三种类型;
按照对事件描述内容的不同,分为过程性指标和结果性指标;
对标签的分类:
按照标签的变化性分为静态标签和动态标签;
按照标签的指代和评估指标的不同,可分为定性标签和定量标签;
指标最擅长的应用是监测、分析、评价和建模。
标签最擅长的应用是标注、刻画、分类和特征提取。
特别需要指出的是,由于对结果的标注也是一种标签,所以在自然语言处理和机器学习相关的算法应用场景下,标签对于监督式学习有重要价值,只是单纯的指标难以做到的。而指标在任务分配、绩效管理等领域的作用,也是标签无法做到的。
维度就是数据的观察角度,即从哪个角度去分析问题,看待问题。
指标就是从维度的基础上去衡算这个结果的值。
维度:一般是一个离散的值,比如时间维度上每一个独立的日期或地域,因此统计时,可以把维度相同记录的聚合在一起,应用聚合函数做累加、均值、最大值、最小值等聚合计算。
指标:就是被聚合的通计算,即聚合运算的结果,一般是一个连续的值。
数仓工具箱中说维度表的唯一主键应该是代理键而不应该是自然键。有时建模人员不愿意放弃使用自然键,因为他们希望与操作型代码查询事实表,而不希望与维度表做连接操作。然而,应该避免使用包含业务含义的多维键,因为不管我们做出任何假设最终都可能变得无效,因为我们控制不了业务库的变动。
所以数据仓库中维度表与事实表的每个连接应该基于无实际含义的整数代理键。避免使用自然键作为维度表的主键。
数据集市是企业级数据仓库的一个子集,他主要面向部门级业务,并且只面向某个特定的主题。为了解决灵活性和性能之间的矛盾,数据集市就是数据仓库体系结构中增加的一种小型的部门或工作组级别的数据仓库。数据集市存储为特定用户预先计算好的数据,从而满足用户对性能的需求。数据集市可以在一定程度上缓解访问数据仓库的瓶颈。
数据集市和数据仓库的主要区别:数据仓库是企业级的,能为整个企业各个部门的运行提供决策支持手段;而数据集市则是一种微型的数据仓库,它通常有更少的数据,更少的主题区域,以及更少的历史数据,因此是部门级的,一般只能为某个局部范围内的管理人员服务,因此也称之为部门级数据仓库。
数据库与数据仓库的区别实际讲的是 OLTP 与 OLAP 的区别。
操作型处理,叫联机事务处理 OLTP(On-Line Transaction Processing,),也可以称面向交易的处理系统,它是针对具体业务在数据库联机的日常操作,通常对少数记录进行查询、修改。用户较为关心操作的响应时间、数据的安全性、完整性和并发支持的用户数等问题。传统的数据库系统作为数据管理的主要手段,主要用于操作型处理,像Mysql,Oracle等关系型数据库一般属于OLTP。
分析型处理,叫联机分析处理 OLAP(On-Line Analytical Processing)一般针对某些主题的历史数据进行分析,支持管理决策。
首先要明白,数据仓库的出现,并不是要取代数据库。数据库是面向事务的设计,数据仓库是面向主题设计的。数据库一般存储业务数据,数据仓库存储的一般是历史数据。
数据库设计是尽量避免冗余,一般针对某一业务应用进行设计,比如一张简单的User表,记录用户名、密码等简单数据即可,符合业务应用,但是不符合分析。数据仓库在设计是有意引入冗余,依照分析需求,分析维度、分析指标进行设计。
数据库是为捕获数据而设计,数据仓库是为分析数据而设计。
以银行业务为例。数据库是事务系统的数据平台,客户在银行做的每笔交易都会写入数据库,被记录下来,这里,可以简单地理解为用数据库记账。数据仓库是分析系统的数据平台,它从事务系统获取数据,并做汇总、加工,为决策者提供决策的依据。比如,某银行某分行一个月发生多少交易,该分行当前存款余额是多少。如果存款又多,消费交易又多,那么该地区就有必要设立ATM了。
显然,银行的交易量是巨大的,通常以百万甚至千万次来计算。事务系统是实时的,这就要求时效性,客户存一笔钱需要几十秒是无法忍受的,这就要求数据库只能存储很短一段时间的数据。而分析系统是事后的,它要提供关注时间段内所有的有效数据。这些数据是海量的,汇总计算起来也要慢一些,但是,只要能够提供有效的分析数据就达到目的了。
数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它决不是所谓的“大型数据库”。
数据仓库的核心是展现层和提供优质的服务。ETL 及其规范、分层等所做的一切都是为了一个更清晰易用的展现层。
数仓分层的原则:
数据源层:ODS(Operational Data Store)
ODS 层,是最接近数据源中数据的一层,为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可,至于数据的去噪、去重、异常值处理等过程可以放在后面的 DWD 层来做。
数据仓库层:DW(Data Warehouse)
数据仓库层是我们在做数据仓库时要核心设计的一层,在这里,从 ODS 层中获得的数据按照主题建立各种数据模型。
DW 层又细分为 DWD(Data Warehouse Detail)层、DWM(Data WareHouse Middle)层和 DWS(Data WareHouse Servce) 层。
数据明细层:DWD(Data Warehouse Detail)
该层一般保持和 ODS 层一样的数据粒度,并且提供一定的数据质量保证。DWD 层要做的就是将数据清理、整合、规范化、脏数据、垃圾数据、规范不一致的、状态定义不一致的、命名不规范的数据都会被处理。
同时,为了提高数据明细层的易用性,该层会采用一些维度退化手法,将维度退化至事实表中,减少事实表和维表的关联。
另外,在该层也会做一部分的数据聚合,将相同主题的数据汇集到一张表中,提高数据的可用性 。
数据中间层:DWM(Data WareHouse Middle)
该层会在 DWD 层的数据基础上,数据做轻度的聚合操作,生成一系列的中间表,提升公共指标的复用性,减少重复加工。
直观来讲,就是对通用的核心维度进行聚合操作,算出相应的统计指标。
在实际计算中,如果直接从 DWD 或者 ODS 计算出宽表的统计指标,会存在计算量太大并且维度太少的问题,因此一般的做法是,在 DWM 层先计算出多个小的中间表,然后再拼接成一张 DWS 的宽表。由于宽和窄的界限不易界定,也可以去掉 DWM 这一层,只留 DWS 层,将所有的数据再放在 DWS 亦可。
数据服务层:DWS(Data WareHouse Servce)
DWS 层为公共汇总层,会进行轻度汇总,粒度比明细数据稍粗,基于 DWD 层上的基础数据,整合汇总成分析某一个主题域的服务数据,一般是宽表。DWS 层应覆盖 80% 的应用场景。又称数据集市或宽表。
按照业务划分,如主题域流量、订单、用户等,生成字段比较多的宽表,用于提供后续的业务查询,OLAP 分析,数据分发等。
一般来讲,该层的数据表会相对比较少,一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。
数据应用层(ADS,Application Data Service)
在这里,主要是提供给数据产品和数据分析使用的数据,一般会存放在 ES、 PostgreSql、Redis 等系统中供线上系统使用,也可能会存在 Hive 或者 Druid 中供数据分析和数据挖掘使用。比如我们经常说的报表数据,一般就放在这里。
维表层:DIM(Dimension)
如果维表过多,也可针对维表设计单独一层,维表层主要包含两部分数据:
数仓建模在哪层建设呢?
那数仓建模怎么建呢?
其实数据仓库的建模方法有很多种,每一种建模方法代表了哲学上的一个观点,代表了一种归纳、概括世界的一种方法。常见的有 范式建模法、维度建模法、实体建模法等,每种方法从本质上将是从不同的角度看待业务中的问题。
范式建模法(Third Normal Form,3NF)
范式建模法其实是我们在构建数据模型常用的一个方法,该方法的主要由 Inmon 所提倡,主要解决关系型数据库的数据存储,利用的一种技术层面上的方法。目前,我们在关系型数据库中的建模方法,大部分采用的是三范式建模法。
范式 是符合某一种级别的关系模式的集合。构造数据库必须遵循一定的规则,而在关系型数据库中这种规则就是范式,这一过程也被称为规范化。目前关系数据库有六种范式:第一范式(1NF)、第二范式(2NF)、第三范式(3NF)、Boyce-Codd范式(BCNF)、第四范式(4NF)和第五范式(5NF)。
在数据仓库的模型设计中,一般采用第三范式。一个符合第三范式的关系必须具有以下三个条件 :
根据 Inmon 的观点,数据仓库模型的建设方法和业务系统的企业数据模型类似。在业务系统中,企业数据模型决定了数据的来源,而企业数据模型也分为两个层次,即主题域模型和逻辑模型。同样,主题域模型可以看成是业务模型的概念模型,而逻辑模型则是域模型在关系型数据库上的实例化。
维度建模法(Dimensional Modeling)
维度模型是数据仓库领域另一位大师Ralph Kimall所倡导,他的《数据仓库工具箱》是数据仓库工程领域最流行的数仓建模经典。维度建模以分析决策的需求出发构建模型,构建的数据模型为分析需求服务,因此它重点解决用户如何更快速完成分析需求,同时还有较好的大规模复杂查询的响应性能。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cSTGCMbT-1654490455767)(数据仓库.assets/image-20220118151308283.png)]
典型的代表是我们比较熟知的星形模型(Star-schema),以及在一些特殊场景下适用的雪花模型(Snow-schema)。
维度建模中比较重要的概念就是 事实表(Fact table)和维度表(Dimension table)。
其最简单的描述就是,按照事实表、维度表来构建数据仓库、数据集市。
实体建模法(Entity Modeling)
实体建模法并不是数据仓库建模中常见的一个方法,它来源于哲学的一个流派。从哲学的意义上说,客观世界应该是可以细分的,客观世界应该可以分成由一个个实体,以及实体与实体之间的关系组成。那么我们在数据仓库的建模过程中完全可以引入这个抽象的方法,将整个业务也可以划分成一个个的实体,而每个实体之间的关系,以及针对这些关系的说明就是我们数据建模需要做的工作。
虽然实体法粗看起来好像有一些抽象,其实理解起来很容易。即我们可以将任何一个业务过程划分成 3 个部分,实体,事件,说明,如下图所示:
上图表述的是一个抽象的含义,如果我们描述一个简单的事实:“小明开车去学校上学”。以这个业务事实为例,我们可以把“小明”,“学校”看成是一个实体,“上学”描述的是一个业务过程,我们在这里可以抽象为一个具体“事件”,而“开车去”则可以看成是事件“上学”的一个说明。
目前在互联网公司最常用的建模方法就是维度建模,我们将重点讲解!
维度建模是专门应用于分析型数据库、数据仓库、数据集市建模的方法。数据集市可以理解为是一种"小型数据仓库"。
我们先不着急开始维度建模,先来了解下维度建模中表的类型和维度建模的模式之后再开始建模,这样能够让我们深刻理解!
维度建模中表的类型
维度建模分为两种表:事实表和维度表:
发生在现实世界中的操作型事件,其所产生的可度量数值,存储在事实表中。从最低的粒度级别来看,事实表行对应一个度量事件,反之亦然。
事实表表示对分析主题的度量。比如一次购买行为我们就可以理解为是一个事实。
图中的订单表就是一个事实表,你可以理解他就是在现实中发生的一次操作型事件,我们每完成一个订单,就会在订单中增加一条记录。事实表的特征:表里没有存放实际的内容,他是一堆主键的集合,这些ID分别能对应到维度表中的一条记录。事实表包含了与各维度表相关联的外键,可与维度表关联。事实表的度量通常是数值类型,且记录数会不断增加,表数据规模迅速增长。
明细表(宽表):
事实表的数据中,有些属性共同组成了一个字段(糅合在一起),比如年月日时分秒构成了时间,当需要根据某一属性进行分组统计的时候,需要截取拼接之类的操作,效率极低。如:
local_time |
---|
2022-02-18 06:31:42 |
为了分析方便,可以事实表中的一个字段切割提取多个属性出来构成新的字段,因为字段变多了,所以称为宽表,原来的成为窄表。
将上述的local_time
字段扩展为如下6个字段:
year | month | day | hour | m | s |
---|---|---|---|---|---|
2022 | 02 | 18 | 06 | 31 | 42 |
又因为宽表的信息更加清晰明细,所以也可以称之为明细表。
事实表种类
事实表分为以下6类,简单解释下每种表的概念:
事务事实表
表中的一行对应空间或时间上某点的度量事件。就是一行数据中必须有度量字段,什么是度量,就是指标,比如说销售金额,销售数量等这些可加的或者半可加就是度量值。另一点就是事务事实表都包含一个与维度表关联的外键。并且度量值必须和事务粒度保持一致。
周期快照事实表
顾名思义,周期事实表就是每行都带有时间值字段,代表周期,通常时间值都是标准周期,如某一天,某周,某月等。粒度是周期,而不是个体的事务,也就是说一个周期快照事实表中数据可以是多个事实,但是它们都属于某个周期内。
累计快照事实表
周期快照事实表是单个周期内数据,而累计快照事实表是由多个周期数据组成,每行汇总了过程开始到结束之间的度量。每行数据相当于管道或工作流,有事件的起点,过程,终点,并且每个关键步骤都包含日期字段。如订单数据,累计快照事实表的一行就是一个订单,当订单产生时插入一行,当订单发生变化时,这行就被修改。
无事实的事实表
我们以上讨论的事实表度量都是数字化的,当然实际应用中绝大多数都是数字化的度量,但是也可能会有少量的没有数字化的值但是还很有价值的字段,无事实的事实表就是为这种数据准备的,利用这种事实表可以分析发生了什么。
聚集事实表
聚集,就是对原子粒度的数据进行简单的聚合操作,目的就是为了提高查询性能。如我们需求是查询全国所有门店的总销售额,我们原子粒度的事实表中每行是每个分店每个商品的销售额,聚集事实表就可以先聚合每个分店的总销售额,这样汇总所有门店的销售额时计算的数据量就会小很多。
合并事实表
这种事实表遵循一个原则,就是相同粒度,数据可以来自多个过程,但是只要它们属于相同粒度,就可以合并为一个事实表,这类事实表特别适合经常需要共同分析的多过程度量。
每个维度表都包含单一的主键列。维度表的主键可以作为与之关联的任何事实表的外键,当然,维度表行的描述环境应与事实表行完全对应。维度表通常比较宽,是扁平型非规范表,包含大量的低粒度的文本属性。
维度表示你要对数据进行分析时所用的一个量,比如你要分析产品销售情况, 你可以选择按类别来进行分析,或按区域来分析。每个类别就构成一个维度。上图中的用户表、商家表、时间表这些都属于维度表,这些表都有一个唯一的主键,然后在表中存放了详细的数据信息。
总的说来,在数据仓库中不需要严格遵守规范化设计原则。因为数据仓库的主导功能就是面向分析,以查询为主,不涉及数据更新操作。事实表的设计是以能够正确记录历史信息为准则,维度表的设计是以能够以合适的角度来聚合主题内容为准则。
维度表结构
维度表谨记一条原则,包含单一主键列,但有时因业务复杂,也可能出现联合主键,请尽量避免,如果无法避免,也要确保必须是单一的,这很重要,如果维表主键不是单一,和事实表关联时会出现数据发散,导致最后结果可能出现错误。
维度表通常比较宽,包含大量的低粒度的文本属性。
跨表钻取
跨表钻取意思是当每个查询的行头都包含相同的一致性属性时,使不同的查询能够针对两个或更多的事实表进行查询
钻取可以改变维的层次,变换分析的粒度。它包括上钻/下钻:
上钻(roll-up):上卷是沿着维的层次向上聚集汇总数据。例如,对产品销售数据,沿着时间维上卷,可以求出所有产品在所有地区每月(或季度或年或全部)的销售额。
下钻(drill-down):下钻是上钻的逆操作,它是沿着维的层次向下,查看更详细的数据。
退化维度
退化维度就是将维度退回到事实表中。因为有时维度除了主键没有其他内容,虽然也是合法维度键,但是一般都会退回到事实表中,减少关联次数,提高查询性能
多层次维度
多数维度包含不止一个自然层次,如日期维度可以从天的层次到周到月到年的层次。所以在有些情况下,在同一维度中存在不同的层次。
维度表空值属性
当给定维度行没有被全部填充时,或者当存在属性没有被应用到所有维度行时,将产生空值维度属性。上述两种情况,推荐采用描述性字符串代替空值,如使用 unknown 或 not applicable 替换空值。
日历日期维度
在日期维度表中,主键的设置不要使用顺序生成的id来表示,可以使用更有意义的数据表示,比如将年月日合并起来表示,即YYYYMMDD,或者更加详细的精度。
星形模式(Star Schema)是最常用的维度建模方式。星型模式是以事实表为中心,所有的维度表直接连接在事实表上,像星星一样。星形模式的维度建模由一个事实表和一组维表成,且具有以下特点:
雪花模式(Snowflake Schema)是对星形模式的扩展。雪花模式的维度表可以拥有其他维度表的,虽然这种模型相比星型更规范一些,但是由于这种模型不太容易理解,维护成本比较高,而且性能方面需要关联多层维表,性能也比星型模型要低。所以一般不是很常用。
星座模式是星型模式延伸而来,星型模式是基于一张事实表的,而星座模式是基于多张事实表的,而且共享维度信息。前面介绍的两种维度建模方法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大部分维度建模都采用的是星座模式。
我们知道维度建模的表类型有事实表,维度表;模式有星形模型,雪花模型,星座模型这些概念了,但是实际业务中,给了我们一堆数据,我们怎么拿这些数据进行数仓建设呢,数仓工具箱作者根据自身60多年的实际业务经验,给我们总结了如下四步,请务必记住!
请牢记以上四步,不管什么业务,就按照这个步骤来,顺序不要搞乱,因为这四步是环环相扣,步步相连。下面详细拆解下每个步骤怎么做
维度建模是紧贴业务的,所以必须以业务为根基进行建模,那么选择业务过程,顾名思义就是在整个业务流程中选取我们需要建模的业务,根据运营提供的需求及日后的易扩展性等进行选择业务。比如商城,整个商城流程分为商家端,用户端,平台端,运营需求是总订单量,订单人数,及用户的购买情况等,我们选择业务过程就选择用户端的数据,商家及平台端暂不考虑。业务选择非常重要,因为后面所有的步骤都是基于此业务数据展开的。
先举个例子:对于用户来说,一个用户有一个身份证号,一个户籍地址,多个手机号,多张银行卡,那么与用户粒度相同的粒度属性有身份证粒度,户籍地址粒度,比用户粒度更细的粒度有手机号粒度,银行卡粒度,存在一对一的关系就是相同粒度。为什么要提相同粒度呢,因为维度建模中要求我们,在同一事实表中,必须具有相同的粒度,同一事实表中不要混用多种不同的粒度,不同的粒度数据建立不同的事实表。并且从给定的业务过程获取数据时,强烈建议从关注原子粒度开始设计,也就是从最细粒度开始,因为原子粒度能够承受无法预期的用户查询。但是上卷汇总粒度对查询性能的提升很重要的,所以对于有明确需求的数据,我们建立针对需求的上卷汇总粒度,对需求不明朗的数据我们建立原子粒度。
维度表是作为业务分析的入口和描述性标识,所以也被称为数据仓库的“灵魂”。在一堆的数据中怎么确认哪些是维度属性呢,如果该列是对具体值的描述,是一个文本或常量,某一约束和行标识的参与者,此时该属性往往是维度属性,数仓工具箱中告诉我们牢牢掌握事实表的粒度,就能将所有可能存在的维度区分开,并且要确保维度表中不能出现重复数据,应使维度主键唯一
事实表是用来度量的,基本上都以数量值表示,事实表中的每行对应一个度量,每行中的数据是一个特定级别的细节数据,称为粒度。维度建模的核心原则之一是同一事实表中的所有度量必须具有相同的粒度。这样能确保不会出现重复计算度量的问题。有时候往往不能确定该列数据是事实属性还是维度属性。记住最实用的事实就是数值类型和可加类事实。所以可以通过分析该列是否是一种包含多个值并作为计算的参与者的度量,这种情况下该列往往是事实。
**数仓建设核心思想:从设计、开发、部署和使用层面,避免重复建设和指标冗余建设,从而保障数据口径的规范和统一,最终实现数据资产全链路关联、提供标准数据输出以及建立统一的数据公共层。**有了核心思想,那怎么开始数仓建设,有句话说数仓建设者即是技术专家,也是大半个业务专家,所以采用的方式就是需求推动数据建设,并且因为数据中台,所以各业务知识体系比较集中,各业务数据不再分散,加快了数仓建设速度。
数仓建设主要从两个方面进行,模型和规范,所有业务进行统一化
所有业务采用统一的模型体系,从而降低研发成本,增强指标复用,并且能保证数据口径的统一
结合公司业务,后期新增需求较多,所以分层不宜过多,并且需要清晰明确各层职责,要保证数据层的稳定又要屏蔽对下游影响,所以采用如下分层结构:
遵循模型开发时分层结构,数据从 ods -> dw -> dm ->app 这样正向流动,可以防止因数据引用不规范而造成数据链路混乱及SLA时效难保障等问题,同时保证血缘关系简洁化,能够轻易追踪数据流向。在开发时应避免以下情况出现:
规范
表命名规范
字段命名规范
构建词根,词根是维度和指标管理的基础,划分为普通词根与专有词根
脚本命名规范
脚本名称:脚本类型.脚本功用.[库名].脚本名称,如 hive.hive.dm.dm_xxsh_users
脚本类型主要分为以下三类:
# 变量的定义要符合python的语法要求
# 指定任务负责人
owner = "[email protected]"
# 脚本存放目录/opt/xxx
# 脚本名称 hive.hive.dm.dm_xxsh_users
# source用来标识上游依赖表,一个任务如果有多个上游表,都需要写进去
# (xxx_name 是需要改动的,其余不需要改)
.....
.....
.....
.....
一些列脚本语句等待执行
数据源层主要将各个业务数据导入到大数据平台,作为业务数据的快照存储。
事实表中的每行对应一个度量,每行中的数据是一个特定级别的细节数据,称为粒度。
维度建模的核心原则之一是同一事实表中的所有度量必须具有相同的粒度。这样能确保不会出现重复计算度量的问题。
维度表一般都是单一主键,少数是联合主键,注意维度表不要出现重复数据,否则和事实表关联会出现数据发散问题。
有时候往往不能确定该列数据是事实属性还是维度属性。记住最实用的事实就是数值类型和可加类事实。所以可以通过分析该列是否是一种包含多个值并作为计算的参与者的度量,这种情况下该列往往是事实;如果该列是对具体值的描述,是一个文本或常量,某一约束和行标识的参与者,此时该属性往往是维度属性。但是还是要结合业务进行最终判断是维度还是事实。
此层命名为轻汇总层,就代表这一层已经开始对数据进行汇总,但是不是完全汇总,只是对相同粒度的数据进行关联汇总,不同粒度但是有关系的数据也可进行汇总,此时需要将粒度通过聚合等操作进行统一。
数据应用层的表就是提供给用户使用的,数仓建设到此就接近尾声了,接下来就根据不同的需求进行不同的取数,如直接进行报表展示,或提供给数据分析的同事所需的数据,或其他的业务支撑。
生产环境中操作不能像我们自己测试时那样随意,一不小心都可能造成生产事故。所以每步操作都要十分小心,需全神贯注,管好大脑管住右手(或左手)。
仅列出以下但不限于以下的注意事项:
- 请勿操作自己管理及授权表之外的其它库表;
- 未经授权,请勿操作生产环境中其他人的脚本及文件;
- 在修改生产环境脚本前,请务必自行备份到本地;
- 请确认自己的修改操作能迅速回滚;
- 生产环境中表名及字段等所有命名请遵循命名规则。
ETL前提
确认ETL范围:通过对目标表信息的收集
选择ETL工具:a.考虑资金 b.运行的平台、对源和目标的支持程度、数据抽取管理监控、对异常处理
确认解决方案:抽取分析、变化数据的捕获、目标表的刷新策略、数据的转换以及数据验证
ETL原则
尽量对数据进行预处理。保证数据的安全性、集成与加载的高效性。
ETL的过程是主动的“拉取”,而不是从内部“推送”,其可控性将大大增加。
流程化的配置管理
数据质量的保证:正确性、一致性、完成性、有效性、可获取性
从源数据导入到数据仓库或者贴源层有两种方式,从源数据拉取数据(pull)和请求源数据推送到数据仓库(push)。一般来讲,后一种方式需要增加业务系统的功能才能进行推送,这个在现实情况中不大行的通,一方面影响业务系统的性能,另一方面增加开发者的工作量,理论上讲,数据仓库不应该要求对源系统做任何的改造,因此一般都采用拉取数据的方式。
确定了数据的抽取方式,还需要确定数据的抽取类型,即全量抽取还是增量抽取。如果数据量小并且容易处理,一般采用全量抽取即可。这种方式适合基础编码类的数据源,最典型的是我们通常所说的数据字典类的码表,在数据仓库中就是维表。如果数据量很大,就只能抽取变化的源数据,即最后一次抽取以来发生了变化的数据。
根据以上原则,确定项目的抽取方式为拉取方式。
抽取类型采用全量抽取、增量抽取。
对所有的维表采用全量抽取,对业务表采用增量抽取的方式
数据转换是将数据进行重构以及标准化,消除数据的不一致,处理缺失数据,转换最主要的任务就是数据清洗。数据清洗是对数据进行重新审查和校验的过程,目的在于删除重复信息,纠正存在的错误,并提供数据一致性。
数据在采集或进行外部接口调用过程中可能会产生不符合要求的“脏数据”,下面介绍下对这些脏数据的产生原因及处理
1 格式内容问题产生的原因
- 不同数据源采集而来的数据内容和格式定义不一致
- 时间、日期格式不一致清洗 根据实际情况,把时间/日期数据库转换成统一的表示方式。
- 数据类型不符清洗
2 逻辑错误清洗
- 数据重复清洗
- 数据不完全相同,但从业务角度看待数据是同一个数据,如页面埋点时,进入页面和退出页面都会上报一次数据,只有时间不一样,其他字段相同,在统计pv/uv时应该进行去重。
- 矛盾内容的修正 如身份证号可以验证我们的年龄,然后我们可以根据字段的数据来源,判断哪个字段提供的信息更为可靠来做修正
3 缺失值的清洗
- 数据值缺失是数据分析中经常遇到的问题之一。
- 造成原因 有些对象的某个或某些属性是不可用的,信息被遗漏,或者实时性高还未来得及做出判断
- 删除元组 这种只适合在对象有多个属性缺失值、被删除的含缺失值的对象与初始数据集的数据量相比非常小的情况下非常有效
- 数据填充用一定的值去填充空值,从而使信息表完备化
- 去空处理 null-string ‘\N’
4 不符合业务需求(或挖掘分析需求)的数据
- 越界数据 如温度 采集如果为10000已经是设备故障等原因导致的,但对后续分析没有意义;视频或文章的播放或查阅时长,不同公司有不同的行业要求,假如要求时长>5m认为是又意义的数据
虽然实时计算在最近几年才火起来,但是在早期也有部分公司有实时计算的需求,但是数据量比较少,所以在实时方面形成不了完整的体系,基本所有的开发都是具体问题具体分析,来一个需求做一个,基本不考虑它们之间的关系,开发形式如下:
如上图所示,拿到数据源后,会经过数据清洗,扩维,通过 Flink 进行业务逻辑处理,最后直接进行业务输出。把这个环节拆开来看,数据源端会重复引用相同的数据源,后面进行清洗、过滤、扩维等操作,都要重复做一遍,唯一不同的是业务的代码逻辑是不一样的。
随着产品和业务人员对实时数据需求的不断增多,这种开发模式出现的问题越来越多:
数据指标越来越多,“烟囱式”的开发导致代码耦合问题严重。
需求越来越多,有的需要明细数据,有的需要 OLAP 分析。单一的开发模式难以应付多种需求。
每个需求都要申请资源,导致资源成本急速膨胀,资源不能集约有效利用。
缺少完善的监控系统,无法在对业务产生影响之前发现并修复问题。
大家看实时数仓的发展和出现的问题,和离线数仓非常类似,后期数据量大了之后产生了各种问题,离线数仓当时是怎么解决的?离线数仓通过分层架构使数据解耦,多个业务可以共用数据,实时数仓是否也可以用分层架构呢?当然是可以的,但是细节上和离线的分层还是有一些不同,稍后会讲到。
在某些场景中,数据的价值随着时间的推移而逐渐减少。所以在传统大数据离线数仓的基础上,逐渐对数据的实时性提出了更高的要求。
于是随之诞生了大数据实时数仓,并且衍生出了两种技术架构Lambda和Kappa。
数据从底层的数据源开始,经过Kafka、Flume等数据组件进行收集,然后分成两条线进行计算:
问题:为什么Lambda架构要分成两条线计算?
假如整个系统只有一个批处理层,会导致用户必须等待很久才能获取计算结果,一般有几个小时的延迟。电商数据分析部门只能查看前一天的统计分析结果,无法获取当前的结果,这对于实时决策来说有一个巨大的时间鸿沟,很可能导致管理者错过最佳决策时机。
Lambda架构属于较早的一种架构方式,早期的流处理不如现在这样成熟,在准确性、扩展性和容错性上,流处理层无法直接取代批处理层,只能给用户提供一个近似结果,还不能为用户提供一个一致准确的结果。因此Lambda架构中,出现了批处理和流处理并存的现象。
在 Lambda 架构中,每层都有自己所肩负的任务。
1. 批处理层存储管理主数据集(不可变的数据集)和预先批处理计算好的视图:
批处理层使用可处理大量数据的分布式处理系统预先计算结果。它通过处理所有的已有历史数据来实现数据的准确性。这意味着它是基于完整的数据集来重新计算的,能够修复任何错误,然后更新现有的数据视图。输出通常存储在只读数据库中,更新则完全取代现有的预先计算好的视图。
2. 流处理层会实时处理新来的大数据:
流处理层通过提供最新数据的实时视图来最小化延迟。流处理层所生成的数据视图可能不如批处理层最终生成的视图那样准确或完整,但它们几乎在收到数据后立即可用。而当同样的数据在批处理层处理完成后,在速度层的数据就可以被替代掉了。
问题:那Lambda架构有没有缺点呢?
Lambda架构经历多年的发展,其优点是稳定,对于实时计算部分的计算成本可控,批量处理可以用晚上的时间来整体批量计算,这样把实时计算和离线计算高峰分开,这种架构支撑了数据行业的早期发展,但是它也有一些致命缺点,并在大数据3.0时代越来越不适应数据分析业务的需求。缺点如下:
导致 Lambda 架构的缺点根本原因是要同时维护两套系统架构:批处理层和速度层。我们已经知道,在架构中加入批处理层是因为从批处理层得到的结果具有高准确性,而加入速度层是因为它在处理大规模数据时具有低延时性。
那我们能不能改进其中某一层的架构,让它具有另外一层架构的特性呢?
例如,改进批处理层的系统让它具有更低的延时性,又或者是改进速度层的系统,让它产生的数据视图更具准确性和更加接近历史数据呢?
另外一种在大规模数据处理中常用的架构——Kappa 架构,便是在这样的思考下诞生的。
Lambda 架构的实时数仓
下图是基于 Flink 和 Kafka 的 Lambda 架构的具体实践,上层是实时计算,下
层是离线计算,横向是按计算引擎来分,纵向是按实时数仓来区分:
Lambda 架构是比较经典的架构,以前实时的场景不是很多,以离线为主,当附加了实时场景后,由于离线和实时的时效性不同,导致技术生态是不一样的。Lambda 架构相当于附加了一条实时生产链路,在应用层面进行一个整合,双路 生产,各自独立。这在业务应用中也是顺理成章采用的一种方式。双路生产会存在一些问题,比如加工逻辑 double,开发运维也会 double,资源同样会变成两个资源链路。因为存在以上问题,所以又演进了一个 Kappa 架构。
Kafka的创始人Jay Kreps认为在很多场景下,维护一套Lambda架构的大数据处理平台耗时耗力,于是提出在某些场景下,没有必要维护一个批处理层,直接使用一个流处理层即可满足需求,即下图所示的Kappa架构:
这种架构只关注流式计算,数据以流的方式被采集过来,实时计算引擎将计算结果放入数据服务层以供查询。可以认为Kappa架构是Lambda架构的一个简化版本,只是去除掉了Lambda架构中的离线批处理部分;
Kappa架构的兴起主要有两个原因:
Kappa架构相对更简单,实时性更好,所需的计算资源远小于Lambda架构,随着实时处理的需求在不断增长,更多的企业开始使用Kappa架构。但这不意味着kappa架构能够取代Lambda架构。
Lambda和kappa架构都有各自的适用领域;
例如流处理与批处理分析流程比较统一,且允许一定的容错,用Kappa比较合适,少量关键指标(例如交易金额、业绩统计等)使用Lambda架构进行批量计算,增加一次校对过程。
还有一些比较复杂的场景,批处理与流处理产生不同的结果(使用不同的机器学习模型,专家系统,或者实时计算难以处理的复杂计算),可能更适合Lambda架构。
Kappa 架构的实时数仓
Kappa 架构相当于去掉了离线计算部分的 Lambda 架构,具体如下图所示:
Kappa 架构从架构设计来讲比较简单,生产统一,一套逻辑同时生产离线和实时。但是在实际应用场景有比较的局限性,因为实时数据的同一份表,会使用不同的方式进行存储,这就导致关联时需要跨数据源,操作数据有很大局限性,所以在业内直接用 Kappa 架构生产落地的案例不多见,且场景比较单一。关于 Kappa 架构,熟悉实时数仓生产的同学,可能会有一个疑问。因为我们经常会面临业务变更,所以很多业务逻辑是需要去迭代的。之前产出的一些数据,如果口径变更了,就需要重算,甚至重刷历史数据。
对于实时数仓来说,怎么去解决数据重算问题?
Kappa 架构在这一块的思路是:首先要准备好一个能够存储历史数据的消息队列,比如 Kafka,并且这个消息队列是可以支持你从某个历史的节点重新开始消费的。接着需要新起一个任务,从原来比较早的一个时间节点去消费 Kafka 上的数据,然后当这个新的任务运行的进度已经能够和现在的正在跑的任务齐平的时候,你就可以把现在任务的下游切换到新的任务上面,旧的任务就可以停掉,并且原来产出的结果表也可以被删掉。
随着实时 OLAP 技术的发展,目前开源的 OLAP 引擎在性能,易用等方面有了很大的提升,如 Doris、Presto 等,加上数据湖技术的迅速发展,使得流批结合的方式变得简单。
数据从日志统一采集到消息队列,再到实时数仓,作为基础数据流的建设是统一的。之后对于日志类实时特征,实时大屏类应用走实时流计算。对于 Binlog 类 业务分析走实时 OLAP 批处理。
我们看到流批结合的方式与上面几种架构的存储方式发生了变化,由 Kafka 换成 了 Iceberg,Iceberg 是介于上层计算引擎和底层存储格式之间的一个中间层,我们可以把它定义成一种“数据组织格式”,底层存储还是 HDFS,那么为什么加了中间层,就对流批结合处理的比较好了呢?Iceberg 的 ACID 能力可以简化整个流水线的设计,降低整个流水线的延迟,并且所具有的修改、删除能力能够有效地降低开销,提升效率。Iceberg 可以有效支持批处理的高吞吐数据扫描和流计算按分区粒度并发实时处理。
数仓建设真正的难点不在于数仓设计,而在于后续业务发展起来,业务线变的庞大之后的数据治理
数据治理的范围很⼴,包含数据本⾝的管理、数据安全、数据质量、数据成本、元数据管理、数据建模等。
为什么要做数据治理?
因为在数据产生、采集、加工、存储、应用到销毁的全过程中,每个环节都可能会引入各种质量、效率或安全相关的问题。在公司早期的发展阶段,这些数据问题对公司发展的影响并不是很大,公司对问题的容忍度相对也比较高。但是,随着业务的发展,公司在利用数据资产创造价值的同时,对数据质量和稳定性要求也有所提升。此外,当数据积累得越来越多,公司对数据精细化运营程度的要求也随之提高,会逐渐发现有很多问题需要治理。
同时,在数据开发的过程中也会不断引入一些问题,而数据治理就是要不断消除引入的这些问题,保障数据准确、全面和完整,为业务创造价值,同时严格管理数据的权限,避免数据泄露带来的业务风险。因此,数据治理是数字时代很多公司一项非常重要的核心能力。
数据治理的范围非常广,其中最重要的是数据质量治理,而数据质量涉及的范围也很广,贯穿数仓的整个生命周期,从数据产生->数据接入->数据存储->数据处理->数据输出->数据展示,每个阶段都需要质量治理,评价维度包括完整性、规范性、一致性、准确性、唯一性、关联性等。
质量检测可参考以下维度:
维度 | 衡量标准 |
---|---|
完整性 | 业务指定必须的数据是否缺失,不允许为空字符或者空值等。 例如,数据源是否完整、维度取值是否完整、数据取值是否完整等 |
时效性 | 当需要使用时,数据能否反映当前事实。数据必须及时,能够满足对数据时间的要求。 例如处理(获取、整理、清洗、加载等)的及时性。 |
唯一性 | 在指定的数据集中数据值是否唯一 |
参照完整性 | 数据项是否在父表中有定义 |
依赖一致性 | 数据项取值是否满足与其他数据项之间的依赖关系 |
正确性 | 数据内容和定义是否一致 |
精确性 | 数据精度是否达到业务规则要求的位数 |
技术有效性 | 数据项是否按已定义的格式标准组织 |
业务有效性 | 数据项是否符合已定义的 |
可信度 | 根据客户调查或客户主动提供获得 |
可用性 | 数据可用的时间和数据需要被访问时间的比例 |
可访问性 | 数据是否便于自动化读取 |
规范是数仓建设的保障。为了避免出现指标重复建设和数据质量差的情况,统一按照最详细、可落地的方法进行规范建设。
(1) 词根
词根是维度和指标管理的基础,划分为普通词根与专有词根,提高词根的易用性和关联性。
普通词根:描述事物的最小单元体,如:交易-trade
专有词根:具备约定成俗或行业专属的描述体,如:美元-USD。
(2) 表命名规范
通用规范
表命名规则
(3) 指标命名规范
结合指标的特性以及词根管理规范,将指标进行结构化处理。
业务修饰词,用于描述业务场景的词汇,例如 trade-交易。
基础指标,单一的业务修饰词+基础指标词根构建基础指标 ,例如:交易金额-trade_amt。
派生指标,多修饰词+基础指标词根构建派生指标。派生指标继承基础指标的特性,例如:安装门店数量-install_poi_cnt。
数据分层
优秀可靠的数仓体系,往往需要清晰的数据分层结构,即要保证数据层的稳定又要屏蔽对下游的影响,并且要避免链路过长,一般的分层架构如下:
数据流向
稳定业务按照标准的数据流向进行开发,即 ODS–>DWD–>DWA–>APP。非稳定业务或探索性需求,可以遵循 ODS->DWD->APP 或者 ODS->DWD->DWT->APP 两个模型数据流。在保障了数据链路的合理性之后,又在此基础上确认了模型分层引用原则:
元数据可分为技术元数据和业务元数据:
技术元数据为开发和管理数据仓库的 IT 人员使用,它描述了与数据仓库开发、管理和维护相关的数据,包括数据源信息、数据转换描述、数据仓库模型、数据清洗与更新规则、数据映射和访问权限等。
常见的技术元数据有:
业务元数据为管理层和业务分析人员服务,从业务角度描述数据,包括商务术语、数据仓库中有什么数据、数据的位置和数据的可用性等,帮助业务人员更好地理解数据仓库中哪些数据是可用的以及如何使用。
常见的业务元数据有维度及属性(包括维度编码,字段类型,创建人,创建时间,状态等)、业务过程、指标(包含指标名称,指标编码,业务口径,指标类型,责任人,创建时间,状态,sql 等),安全等级,计算逻辑等的规范化定义,用于更好地管理和使用数据。数据应用元数据,如数据报表、数据产品等的配置和运行元数据。
元数据治理主要解决三个问题:
围绕数据安全标准,首先要有数据的分级、分类标准,确保数据在上线前有着准确的密级。第二,针对数据使用方,要有明确的角色授权标准,通过分级分类和 角色授权,来保障重要数据拿不走。第三,针对敏感数据,要有隐私管理标准,保障敏感数据的安全存储,即使未授权用户绕过权限管理拿到敏感数据,也要确保其看不懂。第四,通过制定审计标准,为后续的审计提供审计依据,确保数据走不脱。
很多刚入门的数据人,拿到数据后会立刻开始对数据进行各种探查、统计分析等,企图能立即发现数据背后隐藏的信息和知识。然而忙活了一阵才颓然发现,并不能提炼出太多有价值的信息,白白浪费了大量的时间和精力。比如和数据打交道的过程中,可能会出现以下的场景:
场景一:作为数据分析人员,要统计一下近 7 天用户的购买情况,结果从数仓 中统计完发现,很多数据发生了重复记录,甚至有些数据统计单位不统一。
场景二:业务看报表,发现某一天的成交 gmv 暴跌,经过排查发现,是当天的数据缺失。
造成这一情况的一个重要因素就是忽视了对数据质量的客观评估,没有制定合理的衡量标准,导致没有发现数据已出现问题。所以,进行科学、客观的数据质量衡量标准是非常必要且十分重要的。
数据完整性
完整性指的是数据信息是否存在缺失的状况,数据缺失的情况可能是整个数据记 录缺失,也可能是数据中某个字段信息的记录缺失。
数据规范性
规范性指的是描述数据遵循预定的语法规则的程度,是否符合其定义,比如数据的类型、格式、取值范围等。
数据一致性
一致性是指数据是否遵循了统一的规范,数据集合是否保持了统一的格式。数据质量的一致性主要体现在数据记录的规范和数据是否符合逻辑,一致性并不意味着数值上的绝对相同,而是数据收集、处理的方法和标准的一致。常见的一致性指标有:ID 重合度、属性一致、取值一致、采集方法一致、转化步骤一致。
数据准确性
准确性是指数据记录的信息是否存在异常或错误。和一致性不一样,存在准确性 问题的数据不仅仅只是规则上的不一致,更为常见的数据准确性错误就如乱码, 其次异常的大或者小的数据也是不符合条件的数据。常见的准确性指标有:缺失值占比、错误值占比、异常值占比、抽样偏差、数据噪声。
数据唯一性
唯一性指的是数据库的数据不存在重复的情形。比如真实成交 1 万条,但数据表有 3000 条重复了,成了 1.3 万条成交记录,这种数据不符合数据唯一性。
数据及时性
及时性是指数据从产生到可以查看的时间间隔,也叫数据的延时时长。比如一份数据是统计离线今日的,结果都是第二天甚至第三天才能统计完,这种数据不符合数据及时性。
1)等级定义
根据当数据质量不满足完整性、规范性、一致性、准确性、唯一性、及时性时,对业务的影响程度大小来划分数据的资产等级。
重要程度:L1>L2>L3>L4>Lx。如果一份数据出现在多个应用场景中,则根据其最重要程度进行标记。
2) 等级划分
定义数据资产等级后,我们可以从数据流程链路开始进行数据资产等级标记,完成数据资产等级确认,给不同的数据定义不同的重要程度。
举例:
假设公司有统一的订单服务中心。应用层的应用业务是按照业务线,商品类型和地域统计公司的订单数量和订单金额,命名为 order_num_amount。
假设该应用会影响到整个企业的重要业务决策,我们可以把应用定级为 L2,从而整个数据链路上的表的数据等级,都可以标记为L2-order_num_amount,一直标记到源数据业务系统。
1) 在线系统数据校验
在线业务复杂多变,总是在不断地变更,每一次变更都会带来数据的变化,数据仓库需要适应这多变的业务发展,及时做到数据的准确性。
基于此,在线业务的变更如何高效地通知到离线数据仓库,同样也是需要考虑的问题。为了保障在线数据和离线数据的一致性,我们可以通过工具+人员管理并行的方式来尽可能的解决以上问题:既要在工具上自动捕捉每一次业务的变化,同时也要求开发人员在意识上自动进行业务变更通知。
2) 离线系统数据校验
数据从在线业务系统到数据仓库再到数据产品的过程中,需要在数据仓库这一层完成数据的清洗、加工。正是有了数据的加工,才有了数据仓库模型和数据仓库代码的建设。如何保障数据加过程中的质量,是离线数据仓库保障数据质量的一个重要环节。
代码提交核查:
开发相关的规则引擎,辅助代码提交校验。规则分类大致为:
代码发布核查:
加强测试环节,测试环境测试后再发布到生成环境,且生成环境测试通过后才算发布成功。
任务变更或重跑数据:
在进行数据更新操作前,需要通知下游数据变更原因、变更逻辑、变更时间等信息。下游没有异议后,再按照约定时间执行变更发布操作。
风险点监控主要是针对数据在日常运行过程中容易出现的风险进行监控并设置报警机制,主要包括在线数据和离线数据运行风险点监控。
在线业务系统的数据生产过程需要保证数据质量,主要根据业务规则对数据进行监控。
比如交易系统配置的一些监控规则,如订单拍下时间、订单完结时间、订单支付 金额、订单状态流转等都配置了校验规则。订单拍下时间肯定不会大于当天时间,也不会小于业务上线时间,一旦出现异常的订单创建时间,就会立刻报警,同时报警给到多人。通过这种机制,可以及时发现并解决问题。
随着业务负责程度的提升,会导致规则繁多、规则配置的运行成本增大,这时可以按照我们之前的数据资产等级有针对性的进行监控。
离线数据风险点监控主要包括对数据准确性和数据产出及时性的监控。对数据调度平台上所有数据处理调度进行监控。
总结:明确业务需求并从需求开始控制数据质量,并建立数据质量管理机制。
从业务出发做问题定义,由工具自动、及时发现问题,明确问题责任人,通过邮件、短信等方式进行通知,保证问题及时通知到责任人。跟踪问题整改进度,保证数据质量问题全过程的管理。
稳定业务按照标准的数据流向进行开发,即 ODS –> DWD –> DWS –> APP。
非稳定业务或探索性需求,可以遵循 ODS -> DWD -> APP 或者 ODS -> DWD -> DWM ->APP 两个模型数据流。
在保障了数据链路的合理性之后,也必须保证模型分层引用原则:
需统一规定不同的数据的数据类型,严格按照规定的数据类型执行:
宽表的冗余字段要确保:
保证主题域内,指标口径一致,无歧义。
通过数据分层,提供统一的数据出口,统一对外输出的数据口径,避免同一指标不同口径的情况发生。
增量表
新增数据,增量数据是上次导出之后的新数据。
全量表
每天的所有的最新状态的数据。
快照表
按日分区,记录截止数据日期的全量数据。
拉链表
记录截止数据日期的全量数据。
这部分主要是要通过对历史数据的等级划分与对表类型的划分生成相应的生命周期管理矩阵。
历史数据等级划分
主要将历史数据划分P0、Pl、P2、P3 四个等级,其具体定义如下:
表类型划分
事件型流水表(增量表)
事件型流水表(增量表)指数据无重复或者无主键数据,如日志。
事件型镜像表(增量表)
事件型镜像表(增量表)指业务过程性数据,有主键,但是对于同样主键的属性会发生缓慢变化,如交易、订单状态与时间会根据业务发生变更。
维表
维表包括维度与维度属性数据,如用户表、商品表。
Merge 全量表
Merge 全量表包括业务过程性数据或者维表数据。由于数据本身有新增的或者发生状态变更,对于同样主键的数据可能会保留多份,因此可以对这些数据根据主键进行 Merge 操作,主键对应的属性只会保留最新状态,历史状态保留在前一天分区 中。例如,用户表、交易表等都可以进行 Merge 操作。
ETL 临时表
ETL 临时表是指 ETL 处理过程中产生的临时表数据,一般不建议保留,最多7天。
普通全量表
很多小业务数据或者产品数据,BI一般是直接全量拉取,这种方式效率快,对存储压力也不是很大,而且表保留很长时间,可以根据历史数据等级确定保留策略。
通过上述历史数据等级划分与表类型划分,生成相应的生命周期管理矩阵,如下表所示:
同步规范:
- 一个系统源表只允许同步一次;
- 全量初始化同步和增量同步处理逻辑要清晰;
- 以统计日期和时间进行分区存储;
- 目标表字段在源表不存在时要自动填充处理。
表分类与生命周期:
ods流水全量表:
ods镜像型全量表:
ods增量数据:
ods的etl过程中的临时表:
BDSync非去重数据:
数据质量:
- 全量表必须配置唯一性字段标识;
- 对分区空数据进行监控;
- 对枚举类型字段,进行枚举值变化和分布监控;
- ods表数据量级和记录数做环比监控;
- ods全表都必须要有注释;
设计准则:
共维度在不同的物理表中的字段名称、数据类型、数据内容必须保持一致(历史原因不一致,要做好版本控制)
组合原则:
将维度与关联性强的字段进行组合,一起查询,一起展示,两个维度必须具有天然的关系,如:商品的基本属性和所属品牌。
无相关性:如一些使用频率较小的杂项维度,可以构建一个集合杂项维度的特殊属性。
行为维度:经过计算的度量,但下游当维度处理,例:点击量 0-1000,100-1000等,可以做聚合分类。
拆分与冗余:
针对重要性,业务相关性、源、使用频率等可分为核心表、扩展表。
数据记录较大的维度,可以适当冗余一些子集。
存储及生命周期管理
建议按天分区。
3个月内最大访问跨度<=4天时,建议保留最近7天分区;
3个月内最大访问跨度<=12天时,建议保留最近15天分区;
3个月内最大访问跨度<=30天时,建议保留最近33天分区;
3个月内最大访问跨度<=90天时,建议保留最近120天分区;
3个月内最大访问跨度<=180天时,建议保留最近240天分区;
3个月内最大访问跨度<=300天时,建议保留最近400天分区;
存储及生命周期管理
建议按天分区。
3个月内最大访问跨度<=4天时,建议保留最近7天分区;
3个月内最大访问跨度<=12天时,建议保留最近15天分区;
3个月内最大访问跨度<=30天时,建议保留最近33天分区;
3个月内最大访问跨度<=90天时,建议保留最近120天分区;
3个月内最大访问跨度<=180天时,建议保留最近240天分区;
3个月内最大访问跨度<=300天时,建议保留最近400天分区;
事务型事实表设计准则
周期快照事实表
累积快照事实表
数据仓库的性能是数据仓库建设是否成功的重要标准之一。聚集主要是通过汇总明细粒度数据来获得改进查询性能的效果。通过访问聚集数据,可以减少数据库在响应查询时必须执行的工作量,能够快速响应用户的查询,同时有利于减少不同用访问明细数据带来的结果不一致问题。
聚集的基本原则
聚集的基本步骤
第一步:确定聚集维度
在原始明细模型中会存在多个描述事实的维度,如日期、商品类别、卖家等,这时候需要确定根据什么维度聚集,如果只关心商品的交易额情况,那么就可以根据商品维度聚集数据。
第二步:确定一致性上钻
这时候要关心是按月汇总还是按天汇总,是按照商品汇总还是按照类目汇总,如果按照类目汇总,还需要关心是按照大类汇总还是小类汇总。当然,我们要做的只是了解用户需要什么,然后按照他们想要的进行聚集。
第三步:确定聚集事实
在原始明细模型中可能会有多个事实的度量,比如在交易中有交易额、交易数量等,这时候要明确是按照交易额汇总还是按照成交数量汇总。
公共汇总层设计原则
除了聚集基本的原则外,公共汇总层还必须遵循以下原则:
_Id
表示最近1天,_td
表示截至当天,_nd
表示最近N天。词根属于数仓建设中的规范,属于元数据管理的范畴,现在把这个划到数据治理的一部分。完整的数仓建设是包含数据治理的,只是现在谈到数仓偏向于数据建模, 而谈到数据治理,更多的是关于数据规范、数据管理。
表命名,其实在很大程度上是对元数据描述的一种体现,表命名规范越完善,我 们能从表名获取到的信息就越多。比如:一部分业务是关于货架的,英文名是:rack, rack 就是一个词根,那我们就在所有的表、字段等用到的地方都叫 rack,不要叫成 别的什么。这就是词根的作用,用来统一命名,表达同一个含义。
指标体系中有很多“率”的指标,都可以拆解成 XXX+率,率可以叫 rate,那我 们所有的指标都叫做 XXX+rate。
词根:可以用来统一表名、字段名、主题域名等等。
举例:以流程图的方式来展示,更加直观和易懂,本图侧重 dwm 层表的命名 规范,其余命名是类似的道理:
第一个判断条件是该表的用途,是中间表、原始日志还是业务展示用的表 如果该表被判断为中间表,就会走入下一个判断条件:表是否有 group 操作 通过是否有 group 操作来判断该表该划分在 dwd 层还是 dwm 和 dws 层 如果不是 dwd 层,则需要判断该表是否是多个行为的汇总表(即宽表) 最后再分别填上事业群、部门、业务线、自定义名称和更新频率等信息即可。
分层:表的使用范围
事业群和部门:生产该表或者该数据的团队
业务线:表明该数据是哪个产品或者业务线相关
主题域:分析问题的角度,对象实体
自定义:一般会尽可能多描述该表的信息,比如活跃表、留存表等
更新周期:比如说天级还是月级更新
数仓层次
公用维度:dim
DM层:dm
ODS层:ods
DWD层:dwd
DWS层:dws
周期/数据范围
日快照:d
增量:i
全量:f
周:w
拉链表:l
非分区全量表:a
常规表
常规表是我们需要固化的表,是正式使用的表,是目前一段时间内需要去维护去 完善的表。
规范:分层前缀[dwd|dws|ads]_部门_业务域_主题域_XXX_更新周期|数据范围
业务域、主题域我们都可以用词根的方式枚举清楚,不断完善。
更新周期主要的是时间粒度、日、月、年、周等。
中间表
中间表一般出现在 Job 中,是 Job 中临时存储的中间数据的表,中间表的作 用域只限于当前 Job 执行过程中,Job 一旦执行完成,该中间表的使命就完 成了,是可以删除的(按照自己公司的场景自由选择,以前公司会保留几天 的中间表数据,用来排查问题)。
规范:mid_table_name_[0~9|dim]
table_name 是我们任务中目标表的名字,通常来说一个任务只有一个目标表。这里加上表名,是为了防止自由发挥的时候表名冲突,而末尾大家可以选择自由发挥,起一些有意义的名字,或者简单粗暴,使用数字代替,各有优劣吧,谨慎选择。
通常会遇到需要补全维度的表,这里使用 dim 结尾。
如果要保留历史的中间表,可以加上日期或者时间戳。
临时表
临时表是临时测试的表,是临时使用一次的表,就是暂时保存下数据看看,后续一般不再使用的表,是可以随时删除的表。
规范:tmp_xxx
只要加上 tmp 开头即可,其他名字随意,注意 tmp 开头的表不要用来实际使用,只是测试验证而已。
维度表
维度表是基于底层数据,抽象出来的描述类的表。维度表可以自动从底层表抽象出来,也可以手工来维护。
规范:dim_xxx
维度表,统一以 dim 开头,后面加上,对该指标的描述。
手工表
手工表是手工维护的表,手工初始化一次之后,一般不会自动改变,后面变更,也是手工来维护。
一般来说,手工的数据粒度是偏细的,所以暂时统一放在 dwd 层,后面如果有目标值或者其他类型手工数据,再根据实际情况分层。
规范:dwd_业务域_manual_xxx
手工表,增加特殊的主题域,manual,表示手工维护表。
留存表等
更新周期:比如说天级还是月级更新
数仓层次
公用维度:dim
DM层:dm
ODS层:ods
DWD层:dwd
DWS层:dws
周期/数据范围
日快照:d
增量:i
全量:f
周:w
拉链表:l
非分区全量表:a
常规表
常规表是我们需要固化的表,是正式使用的表,是目前一段时间内需要去维护去 完善的表。
规范:分层前缀[dwd|dws|ads]_部门_业务域_主题域_XXX_更新周期|数据范围
业务域、主题域我们都可以用词根的方式枚举清楚,不断完善。
更新周期主要的是时间粒度、日、月、年、周等。
中间表
中间表一般出现在 Job 中,是 Job 中临时存储的中间数据的表,中间表的作 用域只限于当前 Job 执行过程中,Job 一旦执行完成,该中间表的使命就完 成了,是可以删除的(按照自己公司的场景自由选择,以前公司会保留几天 的中间表数据,用来排查问题)。
规范:mid_table_name_[0~9|dim]
table_name 是我们任务中目标表的名字,通常来说一个任务只有一个目标表。这里加上表名,是为了防止自由发挥的时候表名冲突,而末尾大家可以选择自由发挥,起一些有意义的名字,或者简单粗暴,使用数字代替,各有优劣吧,谨慎选择。
通常会遇到需要补全维度的表,这里使用 dim 结尾。
如果要保留历史的中间表,可以加上日期或者时间戳。
临时表
临时表是临时测试的表,是临时使用一次的表,就是暂时保存下数据看看,后续一般不再使用的表,是可以随时删除的表。
规范:tmp_xxx
只要加上 tmp 开头即可,其他名字随意,注意 tmp 开头的表不要用来实际使用,只是测试验证而已。
维度表
维度表是基于底层数据,抽象出来的描述类的表。维度表可以自动从底层表抽象出来,也可以手工来维护。
规范:dim_xxx
维度表,统一以 dim 开头,后面加上,对该指标的描述。
手工表
手工表是手工维护的表,手工初始化一次之后,一般不会自动改变,后面变更,也是手工来维护。
一般来说,手工的数据粒度是偏细的,所以暂时统一放在 dwd 层,后面如果有目标值或者其他类型手工数据,再根据实际情况分层。
规范:dwd_业务域_manual_xxx
手工表,增加特殊的主题域,manual,表示手工维护表。