Programming Hive Chapter3 (数据类型和文件格式)

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

     注:   本人目前正在学习Hadoop和Hive,边学习,边将Programming Hive翻译共享,一来练习英语,二来当做写笔记。 以此作为Hive学习的开篇。

                     本人技术水平和英语能力有限,有何对原版误解之处和翻译错误之处,还请指出和谅解,谢谢!希望能与各位Hadoop fans以及Hive fans共同学习、共同进步。

     转载请注明出处!

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


第三章 数据类型和文件格式

Hive支持很多关系型数据库都支持的基本数据类型,还支持少有关系型数据库的三种集合数据类型。一个相关的问题是,在文本文件中,这些数据类型是如何展现的,或者说如何描述文本的存储。相较于大多数数据库,Hive有一个特性,即它在文本中数据的编码方式上提供了极大的灵活性。大多数据库对于数据在硬盘上的存储以及数据的生命周期都是完全控制的。为了让你控制这些,Hive提供了各种工具使得对数据的管理和处理变得更加简单。

基本数据类型

Hive支持各种长度的整型、浮点型、布尔型和任意长度的字符串类型。Hive0.8.0添加了时间戳和二进制类型。

表3-1列出了Hive支持的基本数据类型

类型

长度

示例

TINYINT

1字节有符号整型

10

SMALLINT

2字节有符号整型

10

INT

4字节有符号整型

10

BIGINT

8字节有符号整型

10

BOOLEAN

True 或 false

TRUE

FLOAT

单精度浮点型

3.14159

DOUBLE

双精度浮点型

3.14159

STRINg

一些列字符,可用单引号或双引号

‘Now is time’,”for all good men”

TIMESTAMP(v0.8.0+)

整型、浮点型或字符串大小

1327882394(Unix纪元秒数),1327882394.123456789(Unix纪元秒数加毫秒),’2013-10-19 02:03:04.123456789’(JDBC的java.sql.Timestamp格式)

BINARY(v0.8.0+)

一系列字节

如下讨论

表3.1

每一个类型都是在Java中执行的,所以数据类型的一些行为细节跟相应的Java类型是一样的。例如,STRING是由Java String执行,FLOAT由 Java FLOAT执行,等等。

注意,跟其它SQL语言一样,Hive不支持最大长度限制的字符数组。关系型数据库提供这个特点是为了性能优化,因为固定长度的记录更容易查找、扫描等。而对于限制更为松散的Hive,它可能不会包含数据文件,并且对文件格式也相当灵活,Hive依赖于用于分割字段的分隔符。此外,Hadoop和Hive都强调优化硬盘的读写性能,所以相对而言,列值是否为固定长度就不那么重要了。

新数据类型TIMESTAMP的值可以是整型(从Unix纪元时间1970-01-01 00:00:00开始计算秒数)、单精度浮点型(从Unix纪元时间1970-01-01 00:00:00外加9位毫秒数开始计算秒数)、字符串(根据JDBC日期字符串格式约定YYYY-MM-DD hh:mm:ss.fffffffff被解释)。TIMESTAMP被解释成UTC时间,为此,Hive提供了转换时区的内置函数,to_utc_timestamp、from_utc_timestamp。

BINARY类型类似于其它关系型数据库中的VARBINARY类型,BINARY列示存储在行中的,而不像BLOB(BINARYLARGEOBJECT)那样与行分开存储。BINARY的一个用途是,其在一行中包含任意字节以防止Hive将其分列成为数值或字符串等。

注意,如果你的目的是忽略每一行的结尾部分,那么你不需要BINARY。如果一个表的表模式定义了3个列,而数据文件的每一行包含5个值,Hive将会忽略最后两个值。

假设你现在运行这样一个查询:比较单精度浮点列和双精度浮点列,或比较两种不同的整型。Hive隐式的将一个整型转换成更大的整型,将FLOAT转换成DOUBLE,转换任意整型成DOUBLE;

假设你现在运行这样一个查询:将字符串列翻译成数值类型。Hive可以进行显式转换,例如,s是STRING类型,转换成整型:cast(s AS INT)。


集合类型

Hive支持structs,maps,arrays这三种集合类型。

表3-2列出了Hive支持的集合类型

类型

描述

示例

STRUCT

类似于C的结构体,其域可用点号访问

Struct(‘John’,’Doe’)

MAP

键值对,其域通过[key]进行访问

Map(‘first’,’John’,’last’,’Doe’)

ARRAY

同数据类型的有序序列,以0开始的整数进行索引

Array(‘John’,’Doe’)

表3.2
因为使用集合类型会破坏范式,所以大多数关系型数据库不支持这样的集合类型。例如,在传统的数据模型中,struct可能会被多个具有外键关系的表存储。破坏范式的实际问题即造成了数据冗余,以致于耗费不必要的硬盘空间,且当数据发生改变的时候,将导致冗余数据存在潜在的数据不一致。然而,大数据系统,牺牲范式以获得更高的计算吞吐量。当处理TB、PB级的数据时,最快的磁盘磁头寻道是必要的,记录中嵌入的集合可以获得更短的寻道时间,而寻找外键关系需要花费更多的寻道时间。
注:Hive没有各类“键”(指主外键等)的概念,可以通过“索引”实现其功能。
以下是一个表声明,描述了如何使用这些类型,假设employee表在虚构的HR应用中:
CREATE TABLE employees(
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING,FLOAT>,
address STRUCT<street:STRING,city:STRING,state:STRING,zip:INT>);
name是员工们的简单字符串,float类型对于工资大小足够了,subordinates列表是一组字符串值,表示其下属(这里起到的作用是将name作为主键,所以subordinates中的每一个元素都引用到表中的另一个记录,没有下级员工的记录处为空数组),在传统模型中,“关系”将会从员工到其经理建立相应的外键。
deductions是包含一个键值对的映射类型,表示从工资中扣税的部分。键即扣税名称,值即百分比值或绝对数值。在传统模型中,则用多个表记录不同的扣税类型,这些表的行通常都包含了扣税值和一个指向相应员工记录的外键。
address是员工的家庭地址,用struct表示,其域有“街道”、“城市”、“州”、“邮政编码”,并分别有各自的数据类型。
集合类型遵循Java对于泛型的语法规定。例如,MAP<STRING,FLOAT>表示映射中的每一个键都是STRING类型,每一个值都是FLOAT类型。ARRAY<STRING>表示数组中的每一个元素都是STRING类型。STRUCT可以是包括各种类型,但是STRUCT中各位置上的数据类型必须与定义的相同。

数据值的文本文件编码

下面通过最简单的文本文件来开始探寻Hive的文件格式。毫无疑问,你肯定很熟悉以逗号(,)或者制表符作为分隔符的文本文件,即所谓的CSV和TSV,Hive支持这些格式,但是此两者的缺点在于,不用于作为分隔符的逗号和制表符可能内嵌在文本中,因此,HIve默认使用了其它的字符(这些字符基本很少的出现在字符串值当中)。

表3-3列出了Hive默认的分隔符

分隔符

描述

\n

文本文件中行分隔符

^A

所有列的分隔符,在create table语句中用八进制的’\001’明确指定

^B

分隔ARRAY、STRUCT中元素以及MAP中键值对,在create table语句中用八进制的’\002’ 明确指定

^C

分隔MAP中相应的键和值,在create table语句中用八进制的’\003’明确指定

表3.3

前面声明的employee表就是以^A作为行分隔符。类似于Emacs的文本编辑器将会以如下形式表示分隔符(由于文本的一行超过了这里一行的长度,所以这里以空白行作为行的标识):

John Doe^A100000.0^AMary Smith^BTodd Jones^AFederal Taxes^C.2^BState Taxes^C.05^BInsurance^C.1^A1 Michigan Ave.^BChicago^BIL^B60600


Mary Smith^A80000.0^ABill King^AFederal Taxes^C.2BState Taxes^C.05BInsurance^C.1^A100 Ontario St.^BChicago^BIL^B60601


Todd Jones^A70000.0^AFederal Taxes^C.15^BState Taxes^C.03^BInsurance^C.1^A200 Chicago Ave.^BOak Park^BIL^B60700


Bill King^A60000.0^AFederal Taxes^C.15^BState Taxes^C.03^BInsurance^C.1^A300 Obscure Dr.^BObscuria^BIL^B60100

这样的文本阅读起来挺麻烦的,但是可以让Hive去做这个事,接下来从第一行入手来了解分隔符在文本文件中的作用。首先,这种格式有点像如下的JSON(JavaScriptObjectNotation)格式:

{

"name":"john Doe",

"salary":100000.0,

"subordinates":["Mary Smith","Todd Jones"],

"deductions":{

"Federal Taxes":.2,

"State Taxes":    .05,

"Insurance":         .1

},

"address":{

"street":"1 Michigan Ave.",

"city":"Chicago",

"state":   "IL",

"zip":60600

}

}

以下是文本第一行的拆分:

John Doe是名字

100000.0是工资

Mary Smith^BTodd Jones是下属Mary Smith和Todd Jones

Federal Taxes^C.2^BState Taxes^C.05^BInsurance^C.1是扣税,“Federal Taxes”扣20%,“State Taxes”扣5%,“Insurance”扣10%

1 Michigan Ave.^BChicago^BIL^B60600是地址

你也可以重写默认分隔符,在某些应用程序写数据时使用了不同的分隔给定时,重写分隔符是非常必要的。以下是相同的表定义,并且添加了默认分隔符的明确指定:

CREATE TABLE employees(
name STRING,
salary FLOAT,
subordinates ARRAY<STRING>,
deductions MAP<STRING,FLOAT>,
address STRUCT<street:STRING,city:STRING,state:STRING,zip:INT>
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
LINES TERMINATED BY '\n'
STORED AS TEXTFILE;
以上定义中,ROW FORMAT语句必须出现在其它语句之前,STORED AS...语句除外。
字符'\001'是^A的八进制,ROW FORMAT DELIMITED FIELDS TERMINATED BY '\001'意即Hive使用^A分隔字段。
类似的,'\002'是^B的八进制, ROW FORMAT DELIMITEDCOLLECTION ITEMS TERMINATED BY '\002'意即Hive使用^B分隔集合元素。
最后,'\003'是^C的八进制, ROW FORMAT DELIMITEDMAP KEYS TERMINATED BY '\003'意即Hive使用^C分隔map的键和值。
LINES TERMINATED BY ... STORED AS ...语句标识行分隔符,其不要求前面加上 ROW FORMAT DELIMITED关键字。
事实上,Hive目前不支持除'\n'以外的任何字符作为行分隔符。
你可以重写字段、集合以及键和值的分隔符,也可以沿用Hive的默认分隔符,STORED AS TEXTFILE极少用到,因为此书中,将默认使用TEXTFILE文件格式。有其他可选文件格式,这将在第15章中讨论,其中相关的如文件的压缩将在后续的第11章中讨论。
所以,在你明确声明所有的这些语句时,最好在大多数情况下使用默认分隔符,通常只需要提供需要被重写的部分。这些声明只会影响到Hive在读数据文件时所扫描的内容。除非在某些特殊限制情况下,你最好以正确的格式写入数据。例如,以下是以逗号最为字段分隔符的表定义:
CREATE TABLE some_data(
first FLOAT,
second FLOAT,
third FLOAT,
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';
以制表符作为分隔符时用’\t', 这种强大的定制化特点,使得在使用Hive结合其它创建文件的工具以及各种ETL(Extract,Transform,Load)处理过程时更加容易和方便。

读模式
向传统数据库中写数据方式,有加载外数据、写入查询的结果,做更新等,数据库在数据存储上有绝对的控制权,数据库就像是一个守门员,这也就意味着数据库的控制是可以以“数据已写入”的方式执行模式。
Hive在基本的存储上没有这样类似的控制权,有很多方式创建、修改甚至毁坏Hive将要查询的数据数据,因此,Hive只能以“读”的方式执行查询,这就是“读模式”。
这样一来,如果模式和文件内容不匹配怎么办?Hive会尽其所能的读取数据,如果文件中的每一行没有足够的字段匹配模式的话,Hive会将后面的字段补成NULL。如果某些字段是数值类型,而Hive读到相应的位置为非数值的字符串,此时,Hive将为这些字段返回NULL,另外很重要的一点是,Hive会尽可能的尝试从所有错误中进行恢复。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值