Greenplum 实时数据仓库实践——数据仓库简介

Posted wzy0623

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Greenplum 实时数据仓库实践——数据仓库简介相关的知识,希望对你有一定的参考价值。

目录

1.1    什么是数据仓库

1.2    操作型系统与分析型系统

1.2.1 操作型系统

1.2.2 分析型系统

1.2.3 操作型系统和分析型系统对比

1.3 抽取-转换-装载

1.3.1 数据抽取

1.3.2 数据转换

1.3.3 数据装载

1.3.4 开发ETL系统的方法

1.4 数据仓库架构

1.4.1 基本架构

1.4.2 主要数据仓库架构

1.4.3 操作数据存储

1.5 实时数据仓库

1.5.1 流式处理

1.5.2 实时计算

1. Lambda架构

2. Kappa架构

1.5.3 实时数据仓库解决方案

小结


        对于每一种技术,先要理解相关的概念和它之所以出现的原因,这对于我们继续深入学习其技术细节大有裨益。实时数据仓库首先是个数据仓库,只是它优先考虑数据的时效性问题。因此本篇开头将介绍业界公认的数据仓库定义,它和操作型数据库应用的区别,以及为什么我们需要数据仓库。
        在对数据仓库的概念有了基本的认识后,有必要单独说明一下ETL这个最重要的过程,然后向读者介绍四种常见的数据仓库架构。本篇最后描述实时数据仓库的产生背景、特定需求和使用场景,并列举一些常见的实时数据仓库技术架构。

1.1    什么是数据仓库

        数据仓库的概念可以追溯到十九世纪八十年代,当时IBM的研究人员开发出了“商业数据仓库”。本质上,数据仓库试图提供一种从操作型系统到决策支持环境的数据流架构模型。数据仓库概念的提出,是为了解决和这个数据流相关的各种问题,主要是解决多重数据复制带来的高成本问题。在没有数据仓库的时代,需要大量的冗余数据来支撑多个决策支持环境。在大组织里,多个决策支持环境独立运作是典型的情况。尽管每个环境服务于不同的用户,但这些环境经常需要大量相同的数据。处理过程收集、清洗、整合来自多个数据源的数据,并为每个决策支持环境做部分数据复制。数据源通常是早已存在的操作型系统,很多是遗留系统。此外,当一个新的决策支持环境形成时,操作型系统的数据经常被再次复用。用户访问这些处理后的数据。
数据仓库之父Bill Inmon在1991年出版的《Building the Data Warehouse》一书中首次提出了被广为认可的数据仓库定义。Inmon将数据仓库描述为一个面向主题的、集成的、随时间变化的、非易失的数据集合,用于支持管理者的决策过程。这个定义有些复杂并且难以理解,下面我们将它分解开来进行说明。

  • 面向主题

        传统的操作型系统是围绕机构的功能性应用进行组织的,而数据仓库是面向主题的。主题是一个抽象概念,简单地说就是与业务相关的数据的类别,每一个主题基本对应一个宏观的分析领域。数据仓库被设计成辅助人们分析数据。例如,一个公司要分析销售数据,就可以建立一个专注于销售的数据仓库,使用这个数据仓库,就可以回答类似于“去年谁是我们这款产品的最佳用户”这样的问题。这个场景下的销售,就是一个数据主题,而这种通过划分主题定义数据仓库的能力,就使得数据仓库是面向主题的。主题域是对某个主题进行分析后确定的主题的边界,如客户、销售、产品都是主题域的例子。

  • 集成

        集成的概念与面向主题是密切相关的。还用销售的例子,假设公司有多条产品线和多种产品销售渠道,而每个产品线都有自己独立的销售数据库。此时要想从公司层面整体分析销售数据,必须将多个分散的数据源统一成一致的、无歧义的数据格式后,再放置到数据仓库中。因此数据仓库必须能够解决诸如产品命名冲突、计量单位不一致等等问题。当完成了这些数据整合工作后,该数据仓库就可称为是集成的。

  • 随时间变化

        为了发现业务变化的趋势、存在的问题、或者新的机会,需要分析大量的历史数据。这与联机事务处理(Online Transactional Processin,OLTP)系统形成鲜明的对比。联机事务处理反应的是当前时间点的数据情况,要求高性能、高并发和极短的响应时间,出于这样的需求考虑,联机事务处理系统中一般都将数据依照活跃程度分级,把历史数据迁移到归档数据库中。而数据仓库关注的是数据随时间变化的情况,并且能反映在过去某个时间点的数据是怎样的。换句话说,数据仓库中的数据是反映了某一历史时间点的数据快照,这也就是术语“随时间变化”的含义。当然,任何一个存储结构都不可能无限扩展,数据也不可能只入不出地永久驻留在数据仓库中,它在数据仓库中也有自己的生命周期。到了一定时候,数据会从数据仓库中移除。移除的方式可能是,将细节数据汇总后删除,将老的数据转储到大容量介质后删除,直接物理删除等。

  • 非易失

        非易失指的是,一旦进入到数据仓库中,数据就不应该再有改变。操作型环境中的数据一般都会频繁更新,而在数据仓库环境中一般并不进行数据更新。当改变的操作型数据进入数据仓库时会产生新的记录,这样就保留了数据变化的历史轨迹。也就是说,数据仓库中的数据基本是静态的。这是一个不难理解的逻辑概念。数据仓库的目的就是要根据曾经发生的事件进行分析,如果数据是可修改的,将使历史分析变得没有意义。

        除了以上四个特性外,数据仓库还有一个非常重要的概念就是粒度。粒度问题遍布于数据仓库体系结构的各个部分。粒度是指数据的细节或汇总程度,细节程度越高,粒度级别越低。例如,单个事务是低粒度级别,而全部一个月事务的汇总就是高粒度级别。

        数据粒度一直是数据仓库设计需要重点思考的问题。在早期的操作型系统中,当细节数据被更新时,几乎总是将其存放在最低粒度级别上,而在传统数据仓库环境中,通常都不这样做。例如,如果数据被装载进数据仓库的频率是每天一次,那么一天之内的数据更新将被忽略。

        粒度之所以是数据仓库环境的关键设计问题,是因为它极大地影响数据仓库的数据量和可以进行的查询类型。粒度级别越低,数据量越大,查询的细节程度越高,查询范围越广泛,反之亦然。

        大多数情况下,数据会以很低的粒度级别进入数据仓库,如日志类型的数据或点击流数据,此时应该对数据进行编辑、过滤和汇总,使其适应数据仓库环境的粒度级别。如果得到的数据粒度级别比数据仓库的高,那将意味着在数据存入数据仓库前,开发人员必须花费大量设计和资源来对数据进行拆分。

        现在你应该已经熟悉了数据仓库的概念,那么数据仓库里的数据从哪里来呢?通常数据仓库的数据来自各个业务应用系统。业务系统中的数据形式多种多样,可能是Oracle、mysql、SQLServer等关系数据库里的结构化数据,可能是文本、CSV等平面文件或Word、Excel文档中的非结构化数据,还可能是html、XML等自描述的半结构化数据。这些业务数据经过一系列的数据抽取、转换、清洗,最终以一种统一的格式装载进数据仓库。数据仓库里的数据作为分析用的数据源,提供给后面的即席查询、分析系统、数据集市、报表系统、数据挖掘系统等。

        从以上描述可以看到,从存储的角度看,数据仓库里的数据实际上已经存在于业务应用系统中,那么为什么不能直接操作业务系统中的数据用于分析,而要使用数据仓库呢?实际上在数据仓库技术出现前,有很多数据分析的先驱者已经发现,简单的“直接访问”方式很难良好工作,这样做的失败案例数不胜数。下面列举一些直接访问业务系统无法工作的原因:

  • 某些业务数据由于安全或其它因素不能直接访问。
  • 业务系统的版本变更很频繁,每次变更都需要重写分析系统并重新测试。
  • 很难建立和维护汇总数据来源于多个业务系统版本的报表。
  • 业务系统的列名通常是硬编码,有时仅仅是无意义的字符串,这让编写分析系统更加困难。
  • 业务系统的数据格式,如日期、数字的格式不统一。
  • 业务系统的表结构为事务处理性能而优化,有时并不适合查询与分析。
  • 没有适当的方式将有价值的数据合并进特定应用的数据库。
  • 没有适当的位置存储元数据。
  • 用户需要看到的显示数据字段,有时在数据库中并不存在。
  • 通常事务处理的优先级比分析系统高,所以如果分析系统和事务处理运行在同一硬件之上,分析系统往往性能很差。
  • 有误用业务数据的风险。
  • 极有可能影响业务系统的性能。

        尽管需要增加软硬件的投入,但建立独立数据仓库与直接访问业务数据相比,无论是成本还是带来的好处,这样做都是值得的。随着处理器和存储成本的逐年降低,数据仓库方案的优势更加明显,在经济上也更具可行性。

       无论是建立数据仓库还要实施别的项目,都要从时间、成本、功能等几个角度权衡比较,认真研究一下是否真正需要一个数据仓库,这是一个很好的问题。当你的组织很小,人数很少,业务单一,数据量也不大,可能你真的不需要建立数据仓库。毕竟要想成功建立一个数据仓库并使其发挥应有的作用还是很有难度的,需要大量的人、财、物力,并且即便花费很大的代价完成了数据仓库的建设,在较短一段时间内也不易显现出价值。在没有专家介入而仅凭组织自身力量建立数据仓库时,还要冒相当大的失败风险。但是,当你所在的组织有超过1000名员工,有几十个部门的时候,它所面临的挑战将是完全不同的。在这个充满竞争的时代,做出正确的决策对一个组织至关重要。而要做出最恰当的决策,仅依据对孤立维度的分析是不可能实现的。这时必须要考虑所有相关数据的可用性,而这个数据最好的来源就是一个设计良好的数据仓库。

        假设一个超市连锁企业,在没有实现数据仓库的情况下,最终该企业会发现,要分析商品销售情况是非常困难的,比如哪些商品被售出,哪些没有被售出,什么时间销量上升,哪个年龄组的客户倾向于购买哪些特定商品等等这些问题都无从回答。而给出这些问题的正确答案正是一个具有吸引力的挑战。这只是第一步,必须要搞清楚一个特定商品到底适不适合18-25岁的人群,以决定该商品的销售策略。一旦从数据分析得出的结论是销售该商品的价值在降低,那么必须实施后面的步骤分析在哪里出了问题,并采取相应的措施加以改进。

        在辅助战略决策层面,数据仓库的重要性更加凸显。作为一个企业的经营者或管理者,他必须对某些问题给出答案,以获得超越竞争对手的额外优势。回答这些问题对于基本的业务运营可能不是必须的,但对于企业的生存发展却必不可少。下面是一些常见问题的例子:

  • 如何把公司的市场份额提升5%?
  • 哪些产品的市场表现不令人满意?
  • 哪些代理商需要销售政策的帮助?
  • 提供给客户的服务质量如何?哪些需要改进?

        回答这些战略性问题的关键一环就是数据仓库。就拿“提供给客户的服务质量如何?”这一问题来说,这是管理者最为关心的问题之一。我们可以把这一问题分解成许多具体的小问题,比如第一个问题是,在过去半年中,收到过多少用户反馈?可以在数据仓库上发出对应的查询,并对查询结果进行分析。之所以能够这样做,是因为数据仓库中含有每一条用户反馈信息。

        你可能已经想到了,第二个问题自然就是,在这些用户反馈当中,给出“非常满意”、“一般”,“不满意”的人数分别有多少?下面的问题就是客户所强调的需要改进的地方和广受批评的地方是哪些?这在数据仓库的用户反馈信息中也有一列来表示,它也能从一个侧面反映出客户关心的问题是哪些。以上这三个问题的答案联合在一起,就可以得出客户服务满意度的结论,并且准确定位哪些地方急需改进。

        下面简单总结一下使用数据仓库的好处:

  • 将多个数据源集成到单一数据存储,因此可以使用单一数据查询引擎展示数据。
  • 缓解在事务处理数据库上因执行大查询而产生的资源竞争问题。
  • 维护历史数据。
  • 通过对多个源系统的数据整合,使得在整个企业的角度存在统一的中心视图。
  • 通过提供一致的编码和描述,减少或修正坏数据问题,提高数据质量。
  • 一致性地表示组织信息。
  • 提供所有数据的单一通用数据模型,而不用关心数据源。
  • 重构数据,使数据对业务用户更有意义。
  • 向复杂分析查询交付优秀的查询性能,同时不影响操作型系统。
  • 开发决策型查询更简单。

1.2    操作型系统与分析型系统

        上一小节已经多次提及操作型系统和分析型系统,本小节将详细阐述它们的概念及差异。在一个大组织中,往往都有两种类型的系统,操作型和分析型,而这两种系统大都以数据库作为数据管理、组织和操作的工具。操作型系统完成组织的核心业务,例如下订单、更新库存、记录支付信息等等。这些系统是事务型的,核心目标是尽可能快地处理事务,同时维护数据的一致性和完整性。而分析型系统的主要作用是通过数据分析评估组织的业务经营状况,并进一步辅助决策。

1.2.1 操作型系统

        相信从事过IT或相关工作的读者对操作型系统都不会感到陌生。几乎所有的互联网线上系统、MIS、OA等等都属于这类系统的应用。操作型系统是一类专门用于管理面向事务的应用的信息系统。“事务”一词在这里存在一些歧义,有些人理解事务是一个计算机或数据库的术语,另一些人所理解的事务是指业务或商业交易,这里使用前一种语义。那么什么是数据库技术中的事务呢?这是首先需要明确的概念。

        事务是工作于数据库管理系统(或类似系统)中的一个逻辑单元,该逻辑单元中的操作被以一种独立于其它事务的可靠方式所处理。事务一般代表着数据改变,它提供“all-or-nothing”操作,就是说事务中的一系列操作要么完全执行,要么完全不执行。在数据库中使用事务主要出于两个目的:

  1. 保证工作单元的可靠性。当数据库系统异常宕机时,其中执行的操作或者已经完成或者只有部分完成,很多没有完成的操作此时处于一种模糊状态。在这种情况下,数据库系统必须能够恢复到数据一致的正常状态。
  2. 提供并发访问数据库的多个程序间的隔离。如果没有这种隔离,程序得到的结果很可能是错误的。

        根据事务的定义,引申出事务具有原子性、一致性、隔离性、持久性的特点,也就是数据库领域中常说的事务的ACID特性。

  • 原子性(Atomicity)

        指的是事务中的一系列操作或全执行或不执行,这些操作是不可再分的。原子性可以防止数据被部分修改。银行账号间转账是一个事务原子性的例子。简单地说,从A账号向B账号转账有两步操作:A账号提取,B账号存入。这两个操作以原子性事务执行,使数据库保持一致的状态,即使这两个操作的任何一步失败了,总的金额数不会减少也不会增加。

  • 一致性(Consistency)

        数据库系统中的一致性是指任何数据库事务只能以允许的方式修改数据。任何数据库写操作必须遵循既有的规则,包括约束、级联、触发器以及它们的任意组合。一致性并不保证应用程序逻辑的正确性,但它能够保证不会因为程序错误而使数据库产生违反规则的结果。

  • 隔离性(Isolation)

        在数据库系统中,隔离性决定了其他用户所能看到的事务完整性程度。例如,一个用户正在生成一个采购订单,并且已经生成了订单主记录,但还没有生成订单条目明细记录。此时订单主记录能否被其他并发用户看到呢?这就是由隔离级别决定的。数据库系统中,按照由低到高一般有读非提交、读提交、可重复读、串行化等几种隔离级。数据库系统并不一定实现所有的隔离级别,如Oracle数据库只实现了读提交和串行化,而MySQL、PostgreSQL数据库则提供这全部四种隔离级别。

        隔离级越低,多用户并发访问数据的能力越高,但同时也会增加脏读、丢失更新等并发操作的负面影响。相反,高隔离级降低了并发影响,但需要使用更多的系统资源,也增加了事务被阻塞的可能性。

  • 持久性(Durability)

        数据库系统的持久性保证已经提交的事务是永久保存的。例如,如果一个机票预订报告显示一个座位已经订出,那么即使系统崩溃,被订了的座位也会一直保持被订出的状态。持久性可以通过在事务提交时将事务日志刷新至永久性存储介质来实现。

        了解了事务的基本概念后,我们再来看操作型系统就比较容易理解了。操作型系统通常是高并发、低延迟的系统,具有大量检索、插入、更新操作,事务数量大,但每个事务影响的数据量相对较小。这样的系统很适合在线应用,它们有成千上万的用户同时使用,并要求能够立即响应用户请求。操作型系统常被整合到面向服务的架构(Service-Oriented Architecture,SOA)和Web服务里。对操作型系统应用的主要要求是高可用、高速度、高并发、可恢复和保证数据一致性,在各种互联网应用层出不穷的今天,这些系统要求是显而易见的。

        操作型系统的数据库操作
        在数据库使用上,操作型系统常用的操作是增、改、查,并且通常是插入与更新密集型的,同时会对数据库进行大量并发查询,而删除操作相对较少。操作型系统一般都直接在数据库上修改数据,没有中间过渡区。

        操作型系统的数据库设计
        操作型系统的特征是大量短的事务,并强调快速处理查询。每秒查询数(Queries-per-second,QPS)是操作型系统的一个有效度量指标。针对以上这些特点,数据库设计一定要满足系统的要求。

        在数据库逻辑设计上,操作型系统的应用数据库大都使用规范化设计方法,通常要满足第三范式。这是因为规范化设计能最大限度的消除数据冗余,因而提供更快更高效地方式执行数据库写操作。关于规范化设计概念及其相关内容,会在下一篇“数据仓库设计基础”中做详细说明。

        在数据库物理设计上,应该依据系统所使用的数据库管理系统的具体特点,做出相应的设计,毕竟每种数据库管理系统在实现细节上还是存在很大差异的。下面就以Oracle数据库为例,简要说明在设计操作型系统数据库时应该考虑的问题。

  • 调整回滚段。回滚段是数据库的一部分,其中记录着最终被回滚的事务的行为。这些回滚段信息可以提供读一致性、回滚事务和数据库恢复。
  • 合理使用聚簇。聚簇是一种数据库模式,其中包含有共用一列或多列的多个表。数据库中的聚簇表用于提高连接操作的性能。
  • 适当调整数据块大小。数据块大小应该是操作系统块大小的倍数,并且设置上限以避免不必要的I/O。
  • 设置缓冲区高速缓存大小。合理的缓存大小能够有效避免不必要的磁盘I/O。
  • 动态分配表空间。
  • 合理划分数据库分区。分区最大的作用在于可用性和可维护性,使得数据维护期间保持事务处理的性能。
  • SQL语句优化。有效利用数据库管理系统的优化器,使用最佳的数据访问路径。
  • 避免过度使用索引。大量的数据修改会给索引维护带来压力,从而对整个系统的性能产生负面影响。

        以上所讲的操作型系统都是以数据库系统为核心,而数据库系统为了保持ACID特性,本质上是单一集中式系统。在当今这个信息爆炸的时代,集中式数据库往往已无法支撑业务的需要(从某订票网站和某电商网站的超大瞬时并发量来看,这已是一个不争的事实)。这就给操作型系统带来新的挑战。分布式事务、去中心化、CAP与最终一致性等一系列新的理论和技术为解决系统扩展问题应运而生。这是一个很大的话题,要想说清楚需要很多的扩展知识和大量篇幅,故这里只是点到为止,不做展开。

1.2.2 分析型系统

        在计算机领域,分析型系统是一种快速回答多维分析查询的实现方式。它也是更广泛范畴的所谓商业智能的一部分(商业智能还包含数据库、报表系统、数据挖掘、数据可视化等研究方向)。分析型系统的典型应用包括销售业务分析报告,市场管理报告,业务过程管理(Business Process Management,BPM),预算和预测,金融分析报告及其类似的应用。

        分析型系统的数据库操作
        在数据库层面,分析型系统操作被定义成少量的事务,复杂的查询,处理归档和历史数据。这些数据很少被修改,从数据库抽取数据是最多的操作,也是识别这种系统的关键特征。分析型数据库基本上都是读操作。

        分析型系统的数据库设计
        分析型系统的特征是相对少量的事务,但查询通常非常复杂并且会包含聚合计算,例如今年和去年同时期的数据对比、百分比变化趋势等等。分析型数据库中的数据一般来自于一个企业级数据仓库,是整合过的历史数据。对于分析型系统,吞吐量是一个有效的性能度量指标。

        在数据库逻辑设计上,分析型数据库使用多维数据模型,通常是设计成星型模式或雪花模式。关于多维数据模型的概念及其相关内容,会在下一篇“数据仓库设计基础”中做详细说明。

        在数据库物理设计上,依然以Oracle数据库为例,简要说明在设计分析型系统数据库时应该考虑的一些问题。

  • 表分区。可以独立定义表分区的物理存储属性,将不同分区的数据存放到多个物理文件上,这样做一方面可以分散I/O,另一方面,当数据量非常大时,方便数据维护。再有利用分区消除查询数据时,不用扫描整张表,从而提高查询性能。
  • 位图索引。当查询条件中包含低基数(不同值很少,例如性别)的列,尤其是包含有这些列上的or、and或not这样的逻辑运算时,或者从有大量行的表中返回大量的行时,应考虑位图索引。
  • 物化视图。物化视图物理存储查询所定义的数据,能够自动增量刷新数据,并且可以利用查询重写特性极大地提高查询速度,是分析型系统常用的技术。
  • 并行化操作。可以在查询大量数据时执行并行化操作,这样会导致多个服务器进程为同一个查询语句工作,使该查询得以快速完成,但是会耗费更多的资源。

        随着数据的大量积累和大数据时代的到来,人们对于数据分析的依赖性越来越强,而分析型系统也随之越来越显示出重要。举一个简单的例子,在一家医院中,保存有20年的非常完整的病人信息。医院领导想看到关于最常见的疾病、成功治愈率、实习医生的实习天数等很多相关数据的详细报告。为了满足这个需求,应用分析型系统查询医院信息数据仓库,并通过复杂查询得到结果,然后将报告提交给领导做进一步分析。

1.2.3 操作型系统和分析型系统对比

        操作型系统和分析型系统是两种不同种类的信息系统。它们都与数据库技术相关,数据库提供方法支持这两种系统的功能。操作型系统和分析型系统以完全不同的方式使用数据库,不仅如此,分析型系统更加注重数据分析和报表,而操作型系统的目标是一个伴有大量数据改变的事务优化系统。

        对于学习数据科学及其相关技术的读者,了解这两种信息处理方式的区别至关重要。这也是理解商业智能、数据挖掘、数据仓库、数据模型、ETL处理和大数据等系统的基础。

        通过前面对两种系统的描述,我们可以对比它们的很多方面。表1-1总结了两种系统的主要区别。后面我们进一步讨论每一个容易产生疑惑的对比项,以帮助你能够理解它。

对比项

操作型系统

分析型系统

数据源

应用的操作信息,一般是最原始的数据

历史的、归档的数据,一般来源于数据仓库

侧重点

数据更新

信息的检索或报表

应用

管理系统、交易系统、在线应用等

报表系统、多维分析、决策支持系统等

用户

终端用户、普通雇员

管理人员、市场人员、数据分析师

任务

业务操作

数据分析

数据更新

插入、更新、删除数据,要求快速执行,立即返回结果

大量数据装载,花费时间很长

数据模型

实体关系模型

多维数据模型

设计方法

规范化设计,大量的表和表之间的关系

星型模式或雪花模式,少量的表

备份

定期执行全量或增量备份,不允许数据丢失

简单备份,数据可以重新装载

数据的时间范围

从天到年

几年或几十年

查询

简单查询,快速返回查询结果

复杂查询,执行聚合或汇总操作

速度

快,大表上需要建索引

相对较慢,需要更多的索引

所需空间

小,只存储操作数据

大,需要存储大量历史数据

表1-1 操作型系统和分析型系统对比

        首先两种系统的侧重点不同。操作型系统更适合对已有数据的更新,所以是日常处理工作或在线系统的选择。相反,分析型系统提供在大量存储数据上的分析能力,所以这类系统更适合报表类应用。分析型系统通常是查询历史数据,这有助于得到更准确的分析报告。

        其次因为这两种系统的目标完全不同,所以为了得到更好的性能,使用的数据模型和设计方法也不同。操作型系统数据库通常使用规范化设计,为普通查询和数据修改提供更好的性能。另一方面,分析型数据库具有典型的数据仓库组织形式。

        基于这两个主要的不同点,我们可以推导出两种系统其它方面的区别。操作型系统上的查询更小,而分析型系统上执行的查询要复杂得多。所以通常操作型系统会比分析型系统快很多。

        操作型系统的数据会持续更新,并且更新会立即生效。而分析型系统的数据更新,是由预定义的处理作业同时装载大量的数据集合,并且在装载前需要做数据转换,因此整个数据更新过程需要较长的执行时间。

        由于操作型系统要做到绝对的数据安全和可用性,所以需要实施复杂的备份系统。基本的全量备份和增量备份都是必须要做的。而分析型系统只需要偶尔执行数据备份即可,这一方面是因为这类系统一般不需要保持持续运行,另一方面数据还可以从操作型系统重复装载。

        两种系统的空间需求显然都依赖于它们所存储的数据量。分析型系统要存储大量的历史数据,因此需要更多的存储空间。

1.3 抽取-转换-装载

        前面已经多次提到了ETL一词,它是Extract、Transform、Load三个英文单词首字母的简写,中文意为抽取、转换、装载。ETL是建立数据仓库最重要的处理过程,也是最体现工作量的环节,一般会占到整个数据仓库项目工作量的一半以上。

  • 抽取——从操作型数据源获取数据。
  • 转换——转换数据,使之转变为适用于查询和分析的形式和结构。
  • 装载——将转换后的数据导入到最终的目标数据仓库。

        建立一个数据仓库,就是要把来自于多个异构的源系统的数据集成在一起,放置于一个集中的位置用于数据分析。如果一开始这些源系统数据就是兼容的当然最好,但情况往往不是这样。ETL系统的工作就是要把异构的数据转换成同构的。如果没有ETL,不可能对异构的数据进行程序化的分析。

1.3.1 数据抽取

        抽取操作从源系统获取数据给后续的数据仓库环境使用。这是ETL处理的第一步,也是最重要的一步。数据被成功抽取后,才可以进行转换并装载到数据仓库中。能否正确地获取数据直接关系到后面步骤的成败。数据仓库典型的源系统是事务处理应用,例如,一个销售分析数据仓库的源系统之一,可能是一个订单录入系统,其中包含当前销售订单相关操作的全部记录。

        设计和建立数据抽取过程,在ETL处理乃至整个数据仓库处理过程中,一般是较为耗时的任务。源系统很可能非常复杂并且缺少相应的文档,因此只是决定需要抽取哪些数据可能就已经非常困难了。通常数据都不是只抽取一次,而是需要以一定的时间间隔反复抽取,通过这样的方式把数据的所有变化提供给数据仓库,并保持数据的及时性。除此之外,源系统一般不允许外部系统对它进行修改,也不允许外部系统对它的性能和可用性产生影响,数据仓库的抽取过程要能适应这样的需求。如果已经明确了需要抽取的数据,下一步就该考虑从源系统抽取数据的方法了。

        数据抽取方法
        对抽取方法的选择高度依赖于源系统和目标数据仓库环境的业务需要。一般情况下,不可能因为需要提升数据抽取的性能,而在源系统中添加额外的逻辑,也不能增加这些源系统的工作负载。有时,用户甚至都不允许增加任何“开箱即用”的外部应用系统,这叫做对源系统具有侵入性。下面分别从逻辑和物理两方面介绍数据抽取方法。

        逻辑抽取
        有两种逻辑抽取类型:全量抽取和增量抽取。

        全量抽取
        源系统的数据全部被抽取。因为这种抽取类型影响源系统上当前所有有效的数据,所以不需要跟踪自上次成功抽取以来的数据变化。源系统只需要原样提供现有的数据而不需要附加的逻辑信息(比如时间戳等)。一个全表导出的数据文件或者一个查询源表所有数据的SQL语句,都是全量抽取的例子。

        增量抽取
        只抽取某个事件发生的特定时间点之后的数据。通过该事件发生的时间顺序能够反映数据的历史变化,它可能是最后一次成功抽取,也可能是一个复杂的业务事件,如最后一次财务结算等。必须能够标识出特定时间点之后所有的数据变化。这些发生变化的数据可以由源系统自身来提供,例如能够反映数据最后发生变化的时间戳列,或者是一个原始事务处理之外的,只用于跟踪数据变化的变更日志表。大多数情况下,使用后者意味着需要在源系统上增加抽取逻辑。

        在许多数据仓库中,抽取过程不含任何变化数据捕获技术。取而代之的是,把源系统中的整个表抽取到数据仓库过渡区,然后用这个表的数据和上次从源系统抽取得到的表数据作比对,从而找出发生变化的数据。虽然这种方法不会对源系统造成很大的影响,但显然需要考虑给数据仓库处理增加的负担,尤其是当数据量很大的时候。

        物理抽取
        依赖于选择的逻辑抽取方法,还有能够对源系统所做的操作和所受的限制,存在两种物理数据抽取机制:直接从源系统联机抽取或者间接从一个脱机结构抽取数据。这个脱机结构有可能已经存在,也可能得需要由抽取程序生成。

        联机抽取
        数据直接从源系统抽取。抽取进程或者直连源系统数据库访问它们的数据表,或者连接到一个存储快照日志或变更记录表的中间层系统。注意这个中间层系统并不需要必须和源系统物理分离。

        脱机抽取
        数据不从源系统直接抽取,而是从一个源系统以外的过渡区抽取。过渡区可能已经存在(例如数据库备份文件、关系数据库系统的重做日志、归档日志等),或者抽取程序自己建立。应该考虑以下的存储结构:

  • 数据库备份文件。一般需要数据还原操作才能使用。
  • 备用数据库。如Oracle的DataGuard和MySQL的数据复制等技术。
  • 平面文件。数据定义成普通格式,关于源对象的附加信息(列名、数据类型等等)需要另外处理。
  • 导出文件。关系数据库大都自带数据导出功能,如Oracle的exp/expdp程序和MySQL的mysqldump程序,都可以用于生成导出数据文件。
  • 重做日志和归档日志。每种数据库系统都有自己的日志格式和解析工具。

        变化数据捕获
        抽取处理需要重点考虑增量抽取,也被称为变化数据捕获,简称CDC。假设一个数据仓库系统,在每天夜里的业务低峰时间从操作型源系统抽取数据,那么增量抽取只需要过去24小时内发生变化的数据。变化数据捕获也是建立实时数据仓库的关键技术。

        当你能够识别并获得最近发生变化的数据时,抽取及其后面的转换、装载操作显然都会变得更高效,因为要处理的数据量会小很多。遗憾的是,很多源系统很难识别出最近变化的数据,或者必须侵入源系统才能做到。变化数据捕获是数据抽取中典型的技术挑战。

        常用的变化数据捕获方法有时间戳、快照、触发器和日志四种。相信熟悉数据库的读者对这些方法都不会陌生。时间戳方法需要源系统有相应的数据列表示最后的数据变化。快照方法可以使用数据库系统自带的机制实现,如Oracle的物化视图技术,也可以自己实现相关逻辑,但会比较复杂。触发器是关系数据库系统具有的特性,源表上建立的触发器会在对该表执行insert、update、delete等语句时被触发,触发器中的逻辑用于捕获数据的变化。日志可以使用应用日志或系统日志,这种方式对源系统不具有侵入性,但需要额外的日志解析工作。关于这四种方案的特点,将会在本专题后面的“数据抽取”部分具体说明。

1.3.2 数据转换

        数据从操作型源系统获取后,需要进行多种转换操作。如统一数据类型、处理拼写错误、消除数据歧义、解析为标准格式等等。数据转换通常是最复杂的部分,也是ETL开发中用时最长的一步。数据转换的范围极广,从单纯的数据类型转化到极为复杂的数据清洗技术。

        在数据转换阶段,为了能够最终将数据装载到数据仓库中,需要在已经抽取来的数据上应用一系列的规则和函数。有些数据可能不需要转换就能直接导入到数据仓库。

        数据转换一个最重要的功能是清洗数据,目的是只有“合规”的数据才能进入目标数据仓库。这步操作在不同系统间交互和通信时尤其必要,例如,一个系统的字符集在另一个系统中可能是无效的。另一方面,由于某些业务和技术的需要,也需要进行多种数据转换,例如下面的情况:

  • 只装载特定的数据列。例如,某列为空的数据不装载。
  • 统一数据编码。例如,性别字段,有些系统使用的是1和0,有些是‘M’和‘F’,有些是‘男’和‘女’,统一成‘M’和‘F’。
  • 自由值编码。例如,将‘Male’改成‘M’。
  • 预计算。例如,产品单价 * 购买数量 = 金额。
  • 基于某些规则重新排序以提高查询性能。
  • 合并多个数据源的数据并去重。
  • 预聚合。例如,汇总销售数据。
  • 行列转置。
  • 将一列转为多列。例如,某列存储的数据是以逗号作为分隔符的字符串,将其分割成多列的单个值。
  • 合并重复列。
  • 预连接。例如,查询多个关联表的数据。
  • 数据验证。针对验证的结果采取不同的处理,通过验证的数据交给装载步骤,验证失败的数据或直接丢弃,或记录下来做进一步检查。

1.3.3 数据装载

        ETL的最后步骤是把转换后的数据装载进目标数据仓库。这步操作需要重点考虑两个问题,一是数据装载的效率问题,二是一旦装载过程中途失败了,如何再次重复执行装载过程。

        即使经过了转换、过滤和清洗,去掉了部分噪声数据,但需要装载的数据量还是很大的。执行一次数据装载可能需要几个小时的时间,同时需要占用大量的系统资源。要提高装载的效率,加快装载速度,可以从以下几方面入手。首先保证足够的系统资源。数据仓库存储的都是海量数据,所以要配置高性能的服务器,并且要独占资源,不要与别的系统共用。在进行数据装载时,要禁用数据库约束(唯一性、非空性,检查约束等)和索引,当装载过程完全结束后,再启用这些约束,重建索引,这种方法会很大地提高装载速度。在数据仓库环境中,一般不使用数据库来保证数据的参考完整性,即不使用数据库的外键约束,它应该由ETL工具或程序来维护。

        数据装载过程可能由于多种原因而失败,比如装载过程中某些源表和目标表的结构不一致而导致失败,而这时已经有部分表装载成功了。在数据量很大的情况下,如何能在重新执行装载过程时只装载失败的部分是一个不小的挑战。对于这种情况,实现可重复装载的关键是要记录下失败点,并在装载程序中处理相关的逻辑。还有一种情况,就是装载成功后,数据又发生了改变(比如有些滞后的数据在ETL执行完才进入系统,就会带来数据的更新或新增),这时需要重新再执行一遍装载过程,已经正确装载的数据可以被覆盖,但相同数据不能重复新增。简单的实现方式是先删除再插入,或者用replace into、merge into等类似功能的操作。

        装载到数据仓库里的数据,经过汇总、聚合等处理后交付给多维立方体或数据可视化、仪表盘等报表工具、BI工具做进一步的数据分析。

1.3.4 开发ETL系统的方法

        ETL系统一般都会从多个应用系统整合数据,典型的情况是这些应用系统运行在不同的软硬件平台上,由不同的厂商所支持,各个系统的开发团队也是彼此独立的,随之而来的数据多样性增加了ETL系统的复杂性。

        开发一个ETL系统,常用的方式是使用数据库标准的SQL及其程序化语言,如Oracle的PL/SQL和MySQL的存储过程、用户自定义函数(UDF)等。还可以使用Kettle这样的ETL工具,这些工具都提供多种数据库连接器和多种文件格式的处理能力,并且对ETL处理进行了优化。使用工具的最大好处是减少编程工作量,提高工作效率。如果遇到特殊需求或特别复杂的情况,可能还是需要使用Shell、Java、Python等编程语言开发自己的应用程序。

        ETL过程要面对大量的数据,因此需要较长的处理时间。为了提高ETL的效率,通常这三步操作会并行执行。当数据被抽取时,转换进程同时处理已经收到的数据。一旦某些数据被转换过程处理完,装载进程就会将这些数据导入目标数据仓库,而不会等到前一步工作执行完才开始。

1.4 数据仓库架构

        前面三个小节介绍了数据仓库、操作型系统、分析型系统、ETL等概念,也指出了分析型系统的数据源一般来自数据仓库,而数据仓库的数据来自于操作型系统。本小节从技术角度讨论数据仓库的组成和架构。

1.4.1 基本架构

        “架构”是什么?这个问题从来就没有一个准确的答案。在软件行业,一种被普遍接受的架构定义是指系统的一个或多个结构。结构中包括软件的构建(构建是指软件的设计与实现),构建的外部可以看到属性以及它们之间的相互关系。这里参考此定义,把数据仓库架构理解成构成数据仓库的组件及其之间的关系,那么就有了下面的数据仓库架构图。

图1-1 数据仓库架构

        下面详细说明图1-1中的各个组件及其所起的作用。

        图中显示的整个数据仓库环境包括操作型系统和数据仓库系统两大部分。操作型系统的数据由各种形式的业务数据组成,这其中可能有关系数据库、TXT或CSV文件、HTML或XML文档,还可能存在外部系统的数据,比如网络爬虫抓取来的互联网数据等,数据可能是结构化、半结构化、非结构化的。这些数据经过抽取、转换和装载(ETL)过程进入数据仓库系统。

        这里把ETL过程分成了抽取和转换装载两个部分。抽取过程负责从操作型系统获取数据,该过程一般不做数据聚合和汇总,但是会按照主题进行集成,物理上是将操作型系统的数据全量或增量复制到数据仓库系统的RDS中。转换、装载过程将对数据进行清洗、过滤、汇总、统一格式化等一系列转换操作,使数据转为适合查询的格式,然后装载进数据仓库系统的TDS中。传统数据仓库的基本模式是用一些过程将操作型系统的数据抽取到文件,然后另一些过程将这些文件转化成MySQL或Oracle这样的关系数据库的记录。最后,第三部分过程负责把数据导入进数据仓库。

        RDS(RAW DATA STORES)是原始数据存储的意思。将原始数据保存到数据仓库里是个不错的想法。ETL过程的bug或系统中的其它错误是不可避免的,保留原始数据使得追踪并修改这些错误成为可能。有时数据仓库的用户会有查询细节数据的需求,这些细节数据的粒度与操作型系统的相同。有了RDS,这种需求就很容易实现,用户可以查询RDS里的数据而不必影响业务系统的正常运行。这里的RDS实际上是起到了操作型数据存储(Operational Data Store,ODS)的作用,关于ODS相关内容本小节后面会有详细论述。

        TDS(TRANSFORMED DATA STORES)意为转换后的数据存储。这是真正的数据仓库中的数据。大量的用户会在经过转换的数据集上处理他们的日常查询。如果前面的工作做得好,这些数据将被以保证最重要的和最频繁的查询能够快速执行的方式构建。

        这里的原始数据存储和转换后的数据存储是逻辑概念,它们可能物理存储在一起,也可能分开。当原始数据存储和转换后的数据存储物理上分开时,它们不必使用同样的软硬件。传统数据仓库中,原始数据存储通常是本地文件系统,原始数据被组织进相应的目录中,这些目录是基于数据从哪里抽取或何时抽取建立(例如以日期作为文件或目录名称的一部分);转换后的数据存储一般是某种关系数据库。

        自动化调度组件的作用是自动定期重复执行ETL过程。不同角色的数据仓库用户对数据的更新频率要求也会有所不同,财务主管需要每月的营收汇总报告,而销售人员想看到每天的产品销售数据。作为通用的需求,所有数据仓库系统都应该能够建立周期性自动执行的工作流作业。传统数据仓库一般利用操作系统自带的调度功能(如Linux的cron或Windows的计划任务)实现作业自动执行。

        数据目录有时也被称为元数据存储,它可以提供一份数据仓库中数据的清单。用户通过它应该可以快速解决这些问题:什么类型的数据被存储在哪里,数据集的构建有何区别,数据最后的访问或更新时间等。此外还可以通过数据目录感知数据是如何被操作和转换的。一个好的数据目录是让用户体验到系统易用性的关键。

        查询引擎组件负责实际执行用户查询。传统数据仓库中,它可能是存储转换后数据的Oracle、MySQL等关系数据库系统内置的查询引擎,还可能是以固定时间间隔向其导入数据的OLAP立方体,如Essbase cube。

        用户界面指的是最终用户所使用的接口程序。可能是一个GUI软件,如BI套件的中的客户端软件,也可能就是一个浏览器。

1.4.2 主要数据仓库架构

        在数据仓库技术演化过程中,产生了几种主要的架构方法,包括数据集市架构、Inmon企业信息工厂架构、Kimball数据仓库架构和混合型数据仓库架构。

        数据集市架构
        数据集市是按主题域组织的数据集合,用于支持部门级的决策。有两种类型的数据集市:独立数据集市和从属数据集市。

        独立数据集市集中于部门所关心的单一主题域,数据以部门为基础部署,无需考虑企业级别的信息共享与集成。例如,制造部门、人力资源部门和其它部门都各自有他们自己的数据集市。独立数据集市从一个主题域或一个部门的多个事务系统获取数据,用以支持特定部门的业务分析需要。一个独立数据集市的设计既可以使用实体关系模型也可以使用多维模型。数据分析或商业智能工具直接从数据集市查询数据,并将查询结果显示给用户。一个典型的独立数据集市架构如图1-2所示。

图1-2 独立数据集市架构

        因为一个部门的业务相对于整个企业要简单,数据量也小得多,所以建立部门的独立数据集市具有周期短、见效快的特点。如果从企业整体的视角来观察这些数据集市,你会看到每个部门使用不同的技术,建立不同的ETL过程,处理不同的事务系统,而在多个独立的数据集市之间还会存在数据的交叉与重叠,甚至会有数据不一致的情况。从业务角度看,当部门的分析需求扩展,或者需要分析跨部门或跨主题域的数据时,独立数据市场会显得力不从心。而当数据存在歧义,比如同一个产品,在A部门和B部门的定义不同时,将无法在部门间进行信息比较。

        另外一种数据集市是从属数据集市。如Bill Inmon所说,从属数据集市的数据来源于数据仓库。数据仓库里的数据经过整合、重构、汇总后传递给从属数据集市。从属数据集市的架构如图1-3所示。

图1-3 从属数据集市架构

        建立从属数据集市的好处主要有: