HIVE–基础

对于初级分析师来说,最日常的工作之一就是通过写SQL提取数据进行分析。

在大数据框架中,提供类SQL语言支持的就是Hive,简称为HiveQL。

首先,想要通过HiveQL进行数据提取和处理,前提是至少需要对HiveQL的基本语法、语句结构、数据类型、常用数据处理方法等掌握清楚,也就是至少要知道怎么用。

其次,要想用好Hive这个数据分析工具,就要对它有一个全面了解,才能提高工作效率和问题排查效率。

最后,Hive不仅作为数据分析工具,还普遍被用来进行数仓构建,学好Hive基础知识,有利于更深入地开展数据分析工作。

本文的主要目标是什么?

通过这篇文章,希望能够帮助稍微有一点点Hive或者SQL基础的读者快速了解Hive。

另外,对Hive曾进行过全面学习但大部分知识点稍有遗忘的读者,本文将带你一起回顾一下。

文章内容主要围绕作者认为数据分析工作中需要重点掌握的Hive基础知识进行讲解,每章节将围绕章节主题展开,章节内容中如有提及到读者以前没了解过的专业词汇,为避免讲解重心偏移,将不会进行专门的展开介绍,读者可自行百度补充了解一下。

本文的讲解思路是什么?

围绕数据分析工作中最常使用到的hive基础知识点进行展开,主要分为以下几个部分:

第1部分:主要介绍下Hive可作为数据分析工具和数仓构建工具。

第2部分:为什么要有Hive,主要是对于Hive的优势进行总结归纳。

第3部分:Hive支持的常用数据类型和文件格式。

第4部分:DDL,内外部表的区别,表的创建、修改、删除和数据的导入导出。

第5部分:常用Hive函数,包括函数语法、含义、示例等。

第6部分:如何添加UDF,将通过一个简单示例给出创建一个UDF的完整步骤,以及对每一步所需注意问题点进行说明。

第7部分:表关联,包括内连接(INNER JOIN)、左外连接(LEFT OUTER JOIN)、右外连接(RIGHT OUTER JOIN)、左半开连接(LEFT SEMI JOIN)以及这四大连接类型的效果示例。

话不多说,下面我们进入正式的知识讲解。

Hive的主要用途

作为数据统计分析工具

大数据框架中,Hive的存在为数据的查询、处理和分析提供了更为友好的操作接口。

因为HiveQL的绝大部分语法都是遵循SQL国际标准,非常简洁统一,书写方便,易学易用。只要有一点SQL基础的用户上手Hive的门槛将会很低,所以Hive的主要用途之一就是作为大数据日常工作中的数据分析工具。

作为数据仓库构建工具

Hive的另一个主要用途是作为数仓构建工具,与许多擅长结构化数据的传统 ETL 工具不同,创建 Hive是为了在 Hadoop 分布式文件系统(HDFS)中加载和转换非结构化、结构化或半结构化数据。

对于 ETL 而言,Hive 是一个强大的工具,它提供了一种将非结构化和半结构化数据转化为基于模式的可用数据的方法。

Hive的优势

Hive可以封装MapReduce、Tez等这些引擎的处理过程,让使用者在不了解这些计算引擎具体执行细节的情况下就可以处理数据,使用者只需要学会如何写sql即可。

Hive可很好的解决直接使用 MapReduce、Tez等时所面临的问题,使其具备了以下优势:

操作简单,学习成本低

直接使用 MapReduce、Tez学习成本太高,因为需要了解底层具体执行引擎的处理逻辑,而且需要一定的编码基础;而Hive提供直接使用类SQL语言即可进行数据查询和处理的平台或接口,只要使用者熟悉sql语言即可;

封装程度高,扩展性强

MapReduce、Tez实现复杂查询逻辑开发难度大,因为需要自己写代码实现整个处理逻辑以及完成对数据处理过程的优化,而Hive将很多数据统计逻辑封装成了可直接使用的函数,且支持自定义函数来进行扩展,而且Hive有逻辑和物理优化器,会对执行逻辑进行自动优化。

常用数据类型和文件格式

数据类型

Hive支持的数据类型分为两类,即基本数据类型和复杂数据类型。

基本数据类型

hive 字母大小写 hive区分大小写_数据


和其他的SQL语言一样,这些都是保留字。

需要注意的是所有的这些数据类型都是对Java中接口的实现,因此这些类型的具体行为细节和Java中对应的类型是完全一致的。例如,STRING类型实现的是Java中的String,float实现的是Java中的float,等等。hive中不区分大小写,所以Hive数据类型也可写成小写的形式。

复杂数据类型

hive 字母大小写 hive区分大小写_hive 字母大小写_02


Hive 有三种复杂数据类型 ARRAY、MAP和STRUCT。

ARRAY和MAP与Java中的Array和 Map 类似,而STRUCT与C语言中的Struct类似,它封装了一个命名字段集合,复杂数据类型允许任意层次的嵌套,比如ARRAY里的单个元素依然是一个ARRAY。

Hive的文件格式

Hive可以支持多种文件格式,比如文本格式、sequence文件格式,甚至是用户自定义的文件格式。在介绍Hive常用的几种文件格式之前,先普及下行存储和列存储的概念。

首先我们来看以下这张表:

hive 字母大小写 hive区分大小写_Hive_03


行存储的特点:

查询满足条件的一整行数据的时候,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。而且行存储这种存储格式可以比较方便进行INSERT和UPDATE操作。缺点是当查询只涉及某几个字段的时候,依然会读取所有数据。

列存储的特点:
因为每个字段的数据聚集存储,在查询只涉及少数几个字段的时候,能大大减少读取的数据量,但需要针对查询的几列字段进行重新组装;另外,因为每个字段的数据类型一定是相同的,因此列式存储可以有针对性地设计更好的压缩算法。这种存储格式的缺点是INSERT/UPDATE会比较麻烦。

我们了解了行式存储和列式存储的概念后,接下来一起来学习下Hive中常见的几种文件格式。

名称                                                                                                 特点

hive 字母大小写 hive区分大小写_hive 字母大小写_04


创建本地测试表,格式分别为为TEXTFILE,SEQUENCEFILE,RCFILE和PARQUET。

hive 字母大小写 hive区分大小写_hive 字母大小写_05


hive 字母大小写 hive区分大小写_hive 字母大小写_06


设置压缩配置:

hive 字母大小写 hive区分大小写_字段_07

查看最终文件大小,相比TEXTFILE和SEQUENCEFILE,RCFILE和PARQUET虽然数据加载时性能消耗较大,但是具有较好的压缩比和查询响应。

数据仓库的特点是一次写入、多次读取,因此,整体来看,RCFILE和PARQUET相比其余两种格式具有较明显的优势。如果Hive底层应用的是SPARK引擎进行数据计算的话,那么数据最好存储为PARQUET,因为SPARK对PARQUET格式的数据读写提供了很好的数据读写性能支持和优化。

DDL&数据的导入导出

以上我们对Hive的常用数据类型和文件格式进行了讲解,接下来给大家讲解Hive的DDL,即对库与表的常见操作。

Hive的存储结构包括数据库、表、视图、分区和表数据等。数据库,表,分区等都对应HDFS上的一个目录。表数据对应 HDFS 对应目录下的文件。以下分为库和表两部分来简单总结一下常用的操作语法。

库的相关操作

hive 字母大小写 hive区分大小写_Hive_08


hive 字母大小写 hive区分大小写_字段_09


表的相关操作

在介绍表的常见操作之前,我们先来了解下内部表、外部表、分区(partition)这几个在数据分析工作中经常会提到的概念和知识点。

首先来了解下内部表和外部表。

简单来说,未被external修饰的是内部表(managed table),被external修饰的为外部表(external table),以上讲解文件格式的时候,创建的就是内部表,如果加上external,那么创建的就是外部表,如下。

hive 字母大小写 hive区分大小写_Hive_10


那么,什么情况下,创建内部表,什么情况下,创建外部表,它们之间的区别是什么呢?

那就是要看存入表中的数据是否需要与其他工作"共享",Hive对内部表控制着其数据的生命周期,当我们删除一个内部表时,Hive也会删除掉这个表中的数据。

而外部表,因为有可能存在其他工作也在共享这份数据,那么Hive认为其并非对这份数据完全拥有,所以在删除的时候,只会删除表,而不会删除数据。

所以,内外部表的概念更多的时候,就是为了表达某种意图,即当一份数据需要多方共享的时候,那么就创建为外部表更好。当然,通常情况下,为了避免不小心误操作,删除了表的时候把整个表的数据都删除了,那么,创建表的时候,最好还是创建为外部表最保险。

除了内部表、外部表,Hive中还有一个很重要的表概念,那就是分区表。

什么叫做分区表呢?

举一个例子,比如一家全国性的连锁企业,订单信息量很大,在进行存储时,我们可以考虑按照省份城市分开来存储。这样我们在查询某个特定城市的销售情况时,就不需要全表扫描读入,而是只读取其中一个分区的数据就可以了。

hive 字母大小写 hive区分大小写_hive 字母大小写_11


分区表改变了Hive对数据存储的组织方式,不加分区的情况下,表的存储目录如下:

hive 字母大小写 hive区分大小写_字段_12


市目录下存放具体的数据文件,这些文件中存放着订单信息。需要注意的是,因为分区字段已经反应在目录中了,所以文件中也就没有必要再存放这些字段了,查询的时候,对应数据也只会在对应目录下才能查到。

因此,分区表的优势就是能够减少读取数据量,极大提高查询速度(根据分区字段进行查询的时候)。

以上花了较大篇幅介绍了在Hive的表相关的操作中几个比较重要的基础概念。接下来我们一起来学习下在Hive中建表、如何添加字段、修改字段类型、删除字段、如何添加分区以及如何进行数据的导入和导出吧。

首先因为上文已经就如何创建内部表、外部表和分区表做了示例,以下将只针对另外两种建表方式给出示例。

建表

使用CTAS(create table … as select…)创建表

hive 字母大小写 hive区分大小写_数据_13

添加字段和修改字段类型的时候,都需要重新刷新分区(partition),因为通过上述命令改变的都是表的数据结构,而Hive针对每个分区都存储了一份数据结构,因此,如果想让已存在的分区使用最新的表结构,必须刷新分区。

Hive并没有提供刷新分区的命令,只能用先删除分区再添加的方式实现,具体的命令如下:

删除后再添加分区

hive 字母大小写 hive区分大小写_hive 字母大小写_14


hive 字母大小写 hive区分大小写_Hive_15


hive 字母大小写 hive区分大小写_字段_16


hive 字母大小写 hive区分大小写_字段_17


数据导出很多时候,我们在Hive中执行SELECT语句,希望将最终的结果保存到本地文件或者保存到HDFS系统中或者保存到一个新的表中,Hive提供了方便的关键词,来实现上面所述的功能。

hive 字母大小写 hive区分大小写_数据_18


hive 字母大小写 hive区分大小写_数据_19


常用函数列表

文章开篇第二段曾讲过,Hive所发挥出来的其中一个最主要的优势就是Hive将很多数据统计逻辑封装成了可直接使用的函数,且支持自定义函数来进行扩展。本文将所有常用的函数通过几张表格罗列在下面。

hive 字母大小写 hive区分大小写_数据_20


hive 字母大小写 hive区分大小写_字段_21


hive 字母大小写 hive区分大小写_字段_22

hive 字母大小写 hive区分大小写_hive 字母大小写_23


hive 字母大小写 hive区分大小写_数据_24


hive 字母大小写 hive区分大小写_Hive_25


hive 字母大小写 hive区分大小写_hive 字母大小写_26


hive 字母大小写 hive区分大小写_字段_27


hive 字母大小写 hive区分大小写_字段_28


hive 字母大小写 hive区分大小写_Hive_29


UDF( user defined function)

Hive不仅有很多可直接使用的函数(见上一段内容),还支持用户自定义函数。这样用户就可以结合各种业务场景自己构建UDF(用户自定义函数)以供HiveQL直接调用。

一旦将用户自定义函数加入到用户会话中,它们就将和内置函数一样使用。

Hive自定义临时通用函数的步骤如下,以一个简单示例我们一起来操作一下:

  1. 在类中创建自定义函数。

自定义UDF需要继承org.apache.hadoop.hive.ql.exec.UDF,实现evaluate函数,evaluate函数支持重载。

hive 字母大小写 hive区分大小写_数据_30


查询执行过程中,查询中对应的每个应用到这个函数的地方都会对这个类进行实例化。对于每行输入都会调用evaluate()函数。2.将该类所在的包导出成jar包,放入linux目录下。

hive 字母大小写 hive区分大小写_hive 字母大小写_31


需要注意的是,create temporary function中的temporary 关键字表示的是当前会话中声明的函数只会在当前会话中有效。

因此用户需要在每个会话中都添加jar,然后再创建函数。如果用户需要长期频繁的使用同一个jar和函数的话,可以将相关语句增加到$HOME/.hiverc文件中去。

4.使用临时函数

hive 字母大小写 hive区分大小写_数据_32


删除自定义临时函数时,加上if exists,这样即使该函数不存在,也不会报错。

表关联

Hive支持通常的SQL JOIN语句,但只支持等值连接。

本文将介绍(内连接)INNER JOIN、(左外连接)LEFT OUTER JOIN、(右外连接)RIGHT JOIN、(全连接)FULL OUTER JOIN、(左半开连接)LEFT SEMI JOIN。

表关联的知识点并不复杂,但是想用好表关联,需要大量的实战练习,大家可以在工作中通过各种各样的案例,来加强这块知识的学习,我们在本课程的最后两篇文章,也会给大家提供可以练习的数据和需求案例。

为方便讲解,首先我们创建接下来用于示例的基础表。

hive 字母大小写 hive区分大小写_字段_33


hive 字母大小写 hive区分大小写_数据_34


内连接(INNER JOIN)

内连接通过INNER JOIN关键字标识,实际使用中,INNER可省略不写,它的含义是左右两个集合相乘后,只保留满足ON后面关联条件的记录。所以,可以利用内连接计算两个集合的交集,只需要把集合元素的字段都写在ON后面的关联条件里即可。

示例:

hive 字母大小写 hive区分大小写_Hive_35


左外连接(LEFT OUTER JOIN)

左外连接通过LEFT OUTER关键字标识,实际使用中,OUTER可省略不写。

它的含义是左右两个集合相乘后,LEFT OUTER JOIN操作符左边表中符合WHERE条件的所有记录将被返回,右边表中通过ON条件关联上的部分将返回右边表中指定选择列的值,其余未关联上的部分将通过给右边表的指定返回列赋以NULL值返回。

如果右边表全都与左边表没匹配上,那右边表指定选择列在结果集中将全是NULL值。

示例:

hive 字母大小写 hive区分大小写_Hive_36


右外连接(RIGHT OUTER JOIN)

右外连接与左外连接含义相同,区别在于左外连接是以左边表为主,保留左边表的所有记录,右外连接是以右边表为主,保留右边所有记录。

其实在实际工作中,只要把想保留所有记录的表一直写在左边,那么右外连接基本就用不上了。

示例:

hive 字母大小写 hive区分大小写_hive 字母大小写_37


全连接(FULL OUTER JOIN)

全连接含义是,左右两个集合相乘后,保留满足ON后面关联条件的记录加上左表和右表中原有的但未关联成功的记录。

示例:

hive 字母大小写 hive区分大小写_Hive_38


左半开连接(LEFT SEMI JOIN)

因为Hive中没有类似标准SQL中的in/exists之类的查询,所以需要有替代性的操作来完成类似功能,左半开连接(LEFTSEMI JOIN)就是起到这样的作用。

比如,在SQL中,想要查询a表中id存在于b表中的a表记录,SQL中查询语句如下:

hive 字母大小写 hive区分大小写_hive 字母大小写_39


在hive中通过左半开连接来完成该操作,前提要求LEFT SEMI JOIN操作符右边的表满足ON语句中的判定条件。

hive 字母大小写 hive区分大小写_数据_40

关于左半开连接(LEFT SEMI JOIN),有以下几项特性总结:

1.返回的结果是LEFT SEMI JOIN操作符左边表中的指定选项记录。

2.LEFT SEMI JOIN 的限制是,JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在WHERE 子句、SELECT 子句或其他地方过滤都不行。

3.对于左边表中一条指定的记录,在右边表中一旦找到匹配的记录,Hive就会立即停止扫描。

总结

本文将数据分析工作中可能会涉及到的Hive基础知识提炼出来跟大家一起学习和回顾了一下,主要包括Hive的主要用途及优势、Hive常用数据类型和文件格式、Hive的DDL与数据导入导出、Hive的常用函数列表、Hive的UDF和表关联相关的知识,希望对大家所有帮助。