-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
注: 本人目前正在学习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+) | 一系列字节 | 如下讨论 |
每一个类型都是在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’) |
数据值的文本文件编码
下面通过最简单的文本文件来开始探寻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’明确指定 |
前面声明的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是地址
你也可以重写默认分隔符,在某些应用程序写数据时使用了不同的分隔给定时,重写分隔符是非常必要的。以下是相同的表定义,并且添加了默认分隔符的明确指定: