Hive快速入门

本文的主要内容如下:

  1. Hive概述
  2. Hive安装配置
  3. 数据类型和文件格式
  4. HQL常用操作

1. Hive概述

1.1 为什么使用Hive

Hadoop生态系统的诞生为高效快速地处理大数据带来曙光,但是需要写MapReduce或者Spark任务,入门门槛较高,需要掌握一门编程语言例如Java或者Scala。
我们长久以来习惯于传统的关系型数据库,并且结构化查询语言(SQL)相对来说也比较容易学习,所以能否将类似于关系型数据库的架构应用到Hadoop文件系统,从而可以使用类SQL语言查询和操作数据呢?Hive应运而生。
Hive提供了一个被称为Hive查询语言(HQL)的SQL方言,来查询存储在Hadoop集群中的数据。Hive就相当于是Mysql,Mysql的底层存储引擎是InnoDB,而Hive的引擎就是Hadoop的MapReduce,或者Spark,Hive会将大多数的查询转换成MapReduce任务或者Spark任务,这样就巧妙地将传统SQL语言和Hadoop生态系统结合起来,使仅会SQL的人员就可以轻松编写数据分析任务。

1.2 Hive应用场景

首先了解一下Hive的特点,然后就能判断其应用场景了。
第一,Hive不是一个完整的数据库,它依托并受到HDFS的限制。其中最大的限制就是Hive不支持记录级别的更新、插入或者删除操作。
第二,Hadoop是一个面向批处理的系统,任务的启动需要消耗较长的时间,所以Hive查询延时比较严重。传统数据库秒级查询的任务在Hive中也需要执行较长的时间。
第三,Hive不支持事务。
综上所述,Hive不支持OLTP(On-Line Transaction Processing),而更接近成为一个OLAP(On-Line Analytical Processing)工具。而且仅仅是接近于OLAP,因为Hive的延时性,还没有满足OLAP中的“联机”部分。因此,Hive是最适合数据仓库应用程序的,不需要快速响应给出结果,可以对海量数据进行相关的静态数据分析,数据挖掘,然后形成决策意见或者报表等。

那么,如果用户需要对大规模数据使用OLTP功能又该如何处理呢?此时我们应该选择一个NoSQL数据库如HBase,这种数据库的特点就是随机查询速度快,可以满足实时查询的要求。

2. Hive安装配置

前方团战,请传送:Hive安装配置

3. 数据类型和文件格式

3.1 基本数据类型

Hive中的基本数据类型与Java中对应的类型一一对应,例如STRING就是对应Java中的String,BIGINT对应Java中的Long等。

数据类型长度示例
TINYINT1byte有符号整数20
SMALLINT2byte有符号整数20
INT4byte有符号整数20
BIGINT8byte有符号整数20
BOOLEAN布尔类型,true或falseTRUE
FLOAT单精度浮点数3.1415926
DOUBLE双精度浮点数3.1415926
STRING字符序列。可以指定字符集。可以使用单引号或双引号‘hello world’,”你好世界”
TIMESTAMP整数,浮点数或字符串1327882394(Unix新纪元秒)
1327882394.123456789(Unix新纪元秒并跟随有纳秒数)
’2012-02-03 12:34:56’(JDBC所兼容的 java.sql.Timestamp时间格式)
BINARY字节数组可以包含任意字节

3.2 集合数据类型

1.STRUCT

struct('John', 'Doe')

STRUCT数据类型和Java中的“对象”类似,可以通过“点”符号访问元素内容。例如,如果某个列name的数据类型是STRUCT {first STRING; last STRING} ,那么第一个元素可以通过 name.first 来引用

2.MAP

map('first', 'John', 'last', 'Doe')

MAP是一对键值对元组集合,使用数组表示法(例如[‘key’])可以访问元素。例如,如果某个列name的数据类型是MAP,其中键值对是’first’->’John’和’last’->’Doe’,那么可以通过 name[‘last’] 获取最后一个元素

3.ARRAY

array('John', 'Doe')

数组是一组具有相同类型和名称的变量的集合,编号从0开始。访问数组的方式大家都很熟悉了,就是 name[1] 即可

3.3 Hive文件的格式

传统关系型文件的格式是对外部隐藏的,而Hive文件存储的格式却是我们自定义的,例如下面就是我们存在Hive表中的数据:

imei(STRING)|ip(STRING)|time(TIMESTAMP)|phone(STRING)|ARRAY(STRUCT(crc(STRING),package(STRING)))

860162036187554|183.52.145.84|2016-11-01 00:11:02|Xiaomi|aad8401e,com.kugou.android;135f98f1,com.cleanmaster.mguard_cn
858162036187554|192.34.45.24|2016-10-09 10:11:00|Huawei|ded8401e,com.qq.android;135f98f1,com.cleanmaster.mguard_cn

上面显示的例子是Hive表中的两条记录,对于文本文件来说,每行就是一条记录,而记录与记录之间的分隔符就是换行符,即“\n”,字段与字段之间的分隔符是“|”,数组元素、STRUCT内的元素或MAP中每一个键值对之间通过“;”进行分隔,注意分号需要转义成”\073“,而“,”用来分隔MAP中的键和值。

4. HQL常用操作

接下来会讲解Hive中数据库、表、分区等的一些基本知识和常用操作,也是我们最经常用到的内容。

4.1 数据库操作

1.查看所有数据库

show databases;

这里写图片描述

2.创建数据库

create database if not exists arrival;

Hive数据库所在的目录位于属性 hive.metastore.warehouse.dir 所指定的顶层目录之后,这个配置的默认值是/user/hive/warehouse。Hive会为每个数据库创建一个目录,数据库中的表将会以这个数据库目录的子目录的形式存储。当我们创建arrival数据库时,Hive将会对应地创建一个目录/user/hive/warehouse/arrival.db,如图所示:

这里写图片描述

有一个例外就是default数据库中的表,因为这个数据库本身没有自己的目录。

用户还可以通过如下命令来修改这个默认的位置:

create database if not exists arrival location '/myown/dir';

3.查看数据库信息

desc database arrival;

这里写图片描述

4.删除数据库

drop database if exists arrival;

默认情况下,Hive不允许用户删除一个包含表的数据库。用户要么先删除数据库中的表,然后再删除数据库;要么在删除命令的最后加上关键字cascade,这样可以使Hive自行先删除数据库中表:

drop database if exists arrival cascade;

5.使用数据库
想要直接访问数据库中的表必须先指定数据库,否则需要加前缀,如arrival.table

use arrival

4.2 表操作

1.创建表

CREATE TABLE IF NOT EXISTS arrival.employsalary (
name STRING COMMENT 'Employee name',
salary FLOAT COMMENT 'Employee salary',
subordinates ARRAY<STRING> COMMENT 'Names of subordinates',
deductions MAP<STRING, FLOAT>
COMMENT 'Keys are deductions names, values are percentages',
address STRUCT<street:STRING, city:STRING, state:STRING>
COMMENT 'Home address')
COMMENT 'Description of the table'
PARTITIONED BY (year STRING, month STRING)
ROW FORMAT
DELIMITED FIELDS TERMINATED BY '|'
COLLECTION ITEMS TERMINATED BY '\073'
MAP KEYS TERMINATED BY ','
LINES TERMINATED BY '\n'
STORED AS TEXTFILE
LOCATION '/user/hive/warehouse/arrival.db/employsalary'
TBLPROPERTIES ('creator'='me', 'created_at'='2017-01-01 10:00:00');

首先,如果当前用户所处数据库并非是目标数据库,那么需要在表名前指定数据库,也就是例子中的arrival。
PARTITIONED BY是分区语句,这个后面详细讲。
ROW FORMAT后面的语句就是前面讲的文件中的内容如何分割。
STORED AS TEXTFILE意味着,所有字段都使用字母、数字、字符编码,包括那些国际字符集,而且每一行是一个单独的记录。
LOCATION '/user/hive/warehouse/arrival.db/employsalary'用来自定义表的位置,也可以不指明,此时就是默认位置/user/hive/warehouse/arrival.db/employsalary。
TBLPROPERTIES可以描述表的一些信息。

注意,我们此时创建的表是管理表,有时也称为内部表。因为这种表,Hive会控制着数据的生命周期,当删除一个管理表时,Hive也会删除表中的数据,而这往往是我们不愿意看到的,所以一般我们会创建外部表,就是在TABLE前面加上EXTERNAL关键字:

CREATE EXTERNAL TABLE IF NOT EXISTS arrival.employsalary
...

Hive删除外部表的时候不会删除表中的数据,只会删除表的元数据信息。

2.查看表信息

desc formatted employsalary;

这里写图片描述

3.复制表

CREATE EXTERNAL TABLE IF NOT EXISTS arrival.employsalary_copy
LIKE arrival.employsalary
LOCATION '/user/hive/warehouse/arrival.db/employsalary_copy';

4.删除表

drop table if exists employsalary;

5.通过查询语句向表中插入数据

前面说过Hive没有行级别的数据插入、更新和删除,那么如何往表中装载数据呢?一种方法是直接把文件放在表目录下面,另一种方式是查询一个已有表,将得到的结果数据插入一个新表,相当于从原有表提取数据到新表。

INSERT OVERWRITE TABLE employ
PARTITION(year='2017', month='03')
SELECT es.name, es.salary FROM employsalary es
WHERE es.year='2017' and es.month='03';

这里使用了OVERWRITE关键字,之前分区的内容将会被覆盖掉,如果不想被覆盖可以去掉该关键字或者使用INTO关键字。
还有一个问题,如果表很大分区很多,那每一次执行这个语句都要对表employsalary扫描一次,带来的消耗很大。Hive提供了另一种INSERT语法,可以只扫描一次输入数据,然后按多种方式进行划分。如下例子显示如何向表employ导入三个月的数据并且只扫描一次原表employsalary:

FROM employsalary es
INSERT OVERWRITE TABLE employ
    PARTITION(year='2017', month='01')
    SELECT es.name, es.salary WHERE es.year='2017' and es.month='01'
INSERT OVERWRITE TABLE employ
    PARTITION(year='2017', month='02')
    SELECT es.name, es.salary WHERE es.year='2017' and es.month='02'
INSERT OVERWRITE TABLE employ
    PARTITION(year='2017', month='03')
    SELECT es.name, es.salary WHERE es.year='2017' and es.month='03';

4.3 分区操作

分区的好处不言而喻,当查询的where字句加上分区过滤信息后,查询性能会极大提升,虽然可以没有分区,但由于Hadoop要处理的数据量都很大,所以尽量给表加上分区。而且分区的字段同时也是表中的字段,可以使用select语句查询出来。

1.添加分区

ALTER TABLE employsalary ADD PARTITION(year='2017', month='03')
LOCATION '/user/hive/warehouse/arrival.db/employsalary_copy/2017/03';

2.查看分区

show partitions employsalary;

这里写图片描述

3.修改分区

ALTER TABLE employsalary PARTITION(year='2017', month='03')
SET LOCATION '/user/hive/warehouse/arrival.db/employsalary_copy/2017/01';

4.删除分区

ALTER TABLE employsalary DROP IF EXISTS PARTITION(year='2017', month='03');

对于管理表,即使是使用 ALTER TABLE … ADD PARTITION 语句增加的分区,分区内的数据也是会同时和元数据信息一起被删除的。对于外部表,分区内数据不会被删除。

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值