目录
一、业务场景
1. 操作型数据源
2. 销售订单数据仓库模型设计
二、HIVE相关配置
1. 选择文件格式
2. 选择表类型
3. 支持行级更新
4. Hive事务支持的限制
三、建立数据库表
1. 源数据库表
2. RDS库表
3. TDS库表
四、装载日期维度数据
五、小节
从本篇开始,介绍使用Kettle实现Hadoop数据仓库的ETL过程。我们会引入一个典型的订单业务场景作为示例,说明多维模型及其相关ETL技术在Kettle上的具体实现。本篇首先介绍一个小而典型的销售订单示例,描述业务场景,说明示例中包含的实体和关系,并在MySQL数据库上建立源数据库表并生成初始的数据。我们要在Hive中创建源数据过渡区和数据仓库的表,因此需要了解与Hive创建表相关的技术问题,包括使用Hive建立传统多维数据仓库时,如何选择适当的文件格式,Hive支持哪些表类型,向不同类型的表中装载数据时具有哪些不同特性。我们将以实验的方式对这些问题加以说明。在此基础上,我们就可以编写Hive的HiveQL脚本,建立过渡区和数据仓库中的表。本篇最后会说明日期维度的数据装载方式及其Kettle实现。
一、业务场景
1. 操作型数据源
示例的操作型系统是一个销售订单系统,初始时只有产品、客户、销售订单三个表,实体关系图如图4-1所示。
图4-1 销售订单源系统
这个场景中的表及其属性都很简单。产品表和客户表属于基本信息表,分别存储产品和客户的信息。产品只有产品编号、产品名称、产品分类三个属性,产品编号是主键,唯一标识一个产品。客户有六个属性,除客户编号和客户名称外,还包含省、市、街道、邮编四个客户所在地区属性。客户编号是主键,唯一标识一个客户。在实际应用中,基本信息表通常由其它后台系统维护。销售订单表有六个属性,订单号是主键,唯一标识一条销售订单记录。产品编号和客户编号是两个外键,分别引用产品表和客户表的主键。另外三个属性是订单时间、登记时间和订单金额。订单时间指的是客户下订单的时间,订单金额属性指的是该笔订单需要花费的金额,这些属性的含义很清楚。订单登记时间表示订单录入的时间,大多数情况下它应该等同于订单时间。如果由于某种情况需要重新录入订单,还要同时记录原始订单的时间和重新录入的时间,或者出现某种问题,订单登记时间滞后于下订单的时间,这两个属性值就会不同。本专题后面“迟到的事实”部分会讨论这种情况。
源系统采用关系模型设计,为了减少表的数量,这个系统只做到了2NF。地区信息依赖于邮编,所以这个模型中存在传递依赖。
2. 销售订单数据仓库模型设计
我们使用四步建模法设计星型数据仓库模型。 (1)选择业务流程。在本示例中只涉及一个销售订单的业务流程。 (2)声明粒度。ETL处理时间周期为每天一次,事实表中存储最细粒度的订单事务记录。 (3)确认维度。显然产品和客户是销售订单的维度。日期维度用于业务集成,并为数据仓库提供重要的历史视角,每个数据仓库中都应该有一个日期维度。订单维度是特意设计的,用于后面说明退化维度技术。我们将在后面详细介绍“退化维度”。 (4)确认事实。销售订单是当前场景中唯一的事实。
示例数据仓库的实体关系图如图4-2所示。
图4-2 销售订单数据仓库
作为演示示例,上面实体关系图中的实体属性都很简单,看属性名字便知其含义。除了日期维度外,其它三个维度都在源数据的基础上增加了代理键、版本号、生效日期、过期日期四个属性,用来描述维度变化的历史。当维度属性发生变化时,依据不同的策略,或生成一条新的维度记录,或直接修改原记录。日期维度有其特殊性,该维度数据一旦生成就不会改变,所以不需要版本号、生效日期和过期日期。代理键是维度表的主键。事实表引用维度表的代理键作为自己的外键,四个外键构成了事实表的联合主键。订单金额是当前事实表中的唯一度量。
二、HIVE相关配置
在“数据仓库架构中的ETL”曾经提到Hive可以用于原始数据和转换后的数据仓库数据存储。使用Hive作为多维数据仓库的主要挑战是处理渐变维(SCD)和生成代理键。处理渐变维需要配置Hive支持行级更新,并在建表时选择适当的文件格式。生成代理键在关系数据库中一般都是用自增列(如MySQL)或序列对象(如Oracle),但Hive中没有这样的机制,必须用其它方法实现。在后面“数据转换与装载”中将说明渐变维的概念和Hive中生成代理键的方法。
1. 选择文件格式
Hive是Hadoop上的数据仓库组件,便于查询和管理分布式存储上的大数据集。Hive提供了一种称为HiveQL的语言,允许用户进行类似于SQL的查询。和普遍使用的所有SQL方言一样,它不完全遵守任何一种ANSI SQL标准,并对标准SQL进行了扩展。HiveQL和MySQL的方言最为接近,但是两者还是存在显著差异。HiveQL只处理结构化数据,并且不区分大小写。缺省时Hive使用内建的derby数据库存储元数据,也可以配置Hive使用MySQL、Oracle等关系数据库存储元数据,生产环境建议使用外部数据库存储Hive元数据。Hive里的数据最终存储在HDFS的文件中,常用的数据文件格式有以下4种:
- TEXTFILE
- SEQUENCEFILE
- RCFILE
- ORCFILE
在深入讨论各种类型的文件格式前,先看一下什么是文件格式。所谓文件格式是一种信息被存储或编码成计算机文件的方式。在Hive中文件格式指的是记录以怎样的编码格式被存储到文件中。当我们处理结构化数据时,每条记录都有自己的结构。记录在文件中是如何编码的就定义了文件格式。不同文件格式的主要区别在于它们的数据编码、压缩率、使用的空间和磁盘I/O。
当用户向传统数据库中增加数据的时候,系统会检查写入的数据与表结构是否匹配,如果不匹配则拒绝插入数据,这就是所谓的写时模式。Hive与此不同,它使用的是读时模式,就是直到读取时再进行数据校验。在向Hive装载数据时,它并不验证数据与表结构是否匹配,但这时它会检查文件格式是否和表定义相匹配。
(1)TEXTFILE
TEXTFILE就是普通的文本型文件,是Hadoop里最常用的输入输出格式,也是Hive的缺省文件格式。如果表定义为TEXTFILE,则可以向该表中装载以逗号、TAB或空格作为分隔符的数据,也可以导入JSON格式的数据。文本文件中除了可以包含普通的字符串、数字、日期等简单数据类型外,还可以包含复杂的集合数据类型。如表4-1所示,Hive支持STRUCT、MAP和ARRAY三种集合数据类型。
数据类型 | 描述 | 语法示例 |
---|---|---|
STRUCT | 结构类型可以通过“点”符号访问元素内容。例如,某个列的数据类型是STRUCT{first STRING,last STRING},那么第一个元素可以通过字段名.first来引用。 | columnname struct(first string, last string) |
MAP | MAP是一组键/值对元组集合,使用数组表示法可以访问元素。例如,如果某个列的数据类型是MAP,其中键/值对是’first’/’John’和’last’/’Doe’,那么可以通过字段名[’ last’]获取最后一个元素的值。 | columnname map(string, string) |
ARRAY | 数组是一组具有相同类型和名称的变量集合。这些变量被称为数组的元素,每个数组元素都有一个编号,编号从0开始。例如,数组值为[‘John’,’Doe’],那么第2个元素可以通过字段名[1]进行引用。 | columnname array(string) |
表4-1 Hive的集合数据类型
Hive中缺省的记录和字段分隔符如表4-2所示。TEXTFILE格式缺省每一行被认为是一条记录。
分隔符 | 描述 |
---|---|
n | 对文本文件来说,每行都是一条记录,因此换行符可以分隔记录 |
^A(Ctrl A) | 用于分隔字段。在CREATE TABLE 语句中可以使用八进制编码的 01表示 |
^B(Ctrl B) | 用于分隔ARRARY或STRUCT中的元素,或用于MAP中键/值对之间的分隔。在CREATE TABLE 语句中可以使用八进制编码的 02表示 |
^C(Ctrl C) | 用于MAP中键和值之间的分隔。在CREATE TABLE 语句中可以使用八进制编码的 03表示 |
表4-2 Hive中缺省的记录和字段分隔
(2)SEQUENCEFILE
我们知道Hadoop处理少量大文件比大量小文件的性能要好。如果文件小于Hadoop里定义的块尺寸(Hadoop 2.x缺省是128M),可以认为是小文件。元数据的增长将转化为NameNode的开销。如果有大量小文件,NameNode会成为性能瓶颈。为了解决这个问题,Hadoop引入了sequence文件,将sequence作为存储小文件的容器。
Sequence文件是由二进制键值对组成的平面文件。Hive将查询转换成MapReduce作业时,决定一个给定记录的哪些键/值对被使用。Sequence文件是可分割的二进制格式,主要的用途是联合多个小文件。
(3)RCFILE
RCFILE指的是Record Columnar File,是一种高压缩率的二进制文件格式,被用于在一个时间点操作多行的场景。RCFILEs是由二进制键/值对组成的平面文件,这点与SEQUENCEFILE非常相似。RCFILE以记录的形式存储表中的列,即列存储方式。它先分割行做水平分区,然后分割列做垂直分区。RCFILE把一行的元数据作为键,把行数据作为值。这种面向列的存储在执行数据分析时更高效。
(4)ORCFILE ORC指的是Optimized Record Columnar,就是说相对于其它文件格式,它以更优化的方式存储数据。ORC能将原始数据的大小缩减75%,从而提升了数据处理的速度。OCR比Text、Sequence和RC文件格式有更好的性能,而且ORC是目前Hive中唯一支持事务的文件格式。
应该依据数据需求选择适当的文件格式,例如:
- 如果数据有参数化的分隔符,那么可以选择TEXTFILE格式。
- 如果数据所在文件比块尺寸小,可以选择SEQUENCEFILE格式。
- 如果想执行数据分析,并高效地存储数据,可以选择RCFILE格式。
- 如果希望减小数据所需的存储空间并提升性能,可以选额ORCFILE格式。
多维数据仓库需要处理渐变维(SCD),必然要用到行级更新,而当前的Hive只有ORCFILE文件格式可以支持此功能。因此在我们的销售订单示例中,所有数据仓库里的表,除日期维度表外,其它表都使用ORCFILE格式。日期维度表数据一旦生成就不会修改,所以使用TEXTFILE格式。原始数据存储里的表数据是从源数据库直接导入的,只有追加和覆盖两种导入方式,不存在数据更新的问题,因此使用缺省的TEXTFILE格式。
2. 选择表类型
(1)管理表 管理表有时也被称为内部表,因为Hive会控制这些表中数据的生命周期。默认情况下,Hive会将这些表的数据存储在由hive-site.xml文件中属性hive.metastore.warehouse.dir所定义目录的子目录下。当我们删除一个管理表时,Hive也会删除这个表中的数据。
管理表的主要问题是只能用Hive访问,不方便和其它系统共享数据。例如,假如有一份由Pig或其它工具创建并且主要由这一工具使用的数据,同时希望使用Hive在这份数据上执行一些查询,可是并没有给予Hive对数据的所有权,这时就不能使用管理表了。我们可以创建一个外部表指向这份数据,而并不需要对其具有所有权。(2)外部表 我们来看一个Hive文档中外部表的例子。
代码语言:javascript复制create external table page_view(viewtime int, userid bigint,
page_url string, referrer_url string,
ip string comment 'ip address of the user',
country string comment 'country of origination')
comment 'this is the staging page view table'
row format delimited fields terminated by '