# Hive的体系结构
为了更好地理解Hive如何与Hadoop的基本组件一起协同工作,可以把Hadoop看作一个操作系统,HDFS和MapReduce是这个操作系统的组成部分,而像Hive、HBase这些组件,则是操作系统的上层应用或功能。Hadoop生态圈的通用底层架构是HDFS提供分布式存储,MapReduce为上层功能提供并行处理能力。

在HDFS和MapReduce之上,图中显示了Hive驱动程序和元数据存储。Hive驱动程序及其编译器负责编译、优化和执行HiveQL。依赖于具体情况,Hive驱动程序可能选择在本地执行Hive语句或命令,也可能是产生一个MapReduce作业。Hive驱动程序把元数据存储在数据库中。
默认配置下,Hive在内建的Derby关系数据库系统中存储元数据,这种方式被称为嵌入模式。在这种模式下,Hive驱动程序、元数据存储和Derby全部运行在同一个Java虚拟机中(JVM)。这种配置适合于学习目的,它只支持单一Hive会话,所以不能用于多用户的生产环境。Hive还允许将元数据存储于本地或远程的外部数据库中,这种设置可以更好地支持Hive的多会话生产环境。并且,可以配置任何与JDBC API兼容的关系数据库系统存储元数据,如MySQL、Oracle等。
对应用支持的关键组件是Hive Thrift服务,它允许一个富客户端访问Hive,开源的SQuirreL SQL客户端被作为示例包含其中。任何与JDBC兼容的应用,都可以通过绑定的JDBC驱动访问Hive。与ODBC兼容的客户端,如Linux下典型的unixODBC和isql应用程序,可以从远程Linux客户端访问Hive。如果在客户端安装了相应的ODBC驱动,甚至可以从微软的Excel访问Hive。通过Thrift还可以用Java以外的程序语言,如PHP或Python访问Hive。就像JDBC、ODBC一样,Thrift客户端通过Thrift服务器访问Hive。
架构图的最上面包括一个命令行接口(CLI),可以在Linux终端窗口向Hive驱动程序直接发出查询或管理命令。还有一个简单的Web界面,通过它可以从浏览器访问Hive管理表及其数据。
# Hive 的工作流程
从接收到从命令行或是应用程序发出的查询命令,到把结果返回给用户,期间Hive的工作流程(第一版的MapReduce)如下图,从中不难看出,Hive的执行过程与关系数据库的非常相似,只不过是使用分布式计算框架来实现。

步骤 | 操作 |
---|---|
1.执行查询 | 从Hive的CLI或Web UI发查询命令给驱动程序(任何JDBC、ODBC数据库驱动)执行 |
2.获得计划 | 驱动程序请求查询编译器解析查询、检查语法、生成查询计划或者查询所需要的资源 |
3.获得元数据 | 编译器向元数据存储数据库发送元数据请求 |
4.发送元数据 | 作为响应,元数据存储数据库向编译器发送元数据 |
5.发送计划 | 编译器检查需要的资源,并把查询计划发送给驱动程序。至此,查询解析完成 |
6.执行计划 | 驱动程序向执行引擎发送执行计划 |
7.执行作业 | 执行计划的处理是一个MapReduce作业。执行引擎向Name node上的JobTracker进程发送作业,JobTracker把作业分配给Data node上的TaskTracker进程,此时,查询执行MapReduce作业 |
7.1操作元数据 | 执行作业的同时,执行引擎可能会执行元数据操作,如DDL语句等。 |
8.取回结果 | 执行引擎从Data node 接收结果 |
9.发送结果 | 执行引擎向驱动程序发送合成的结果值 |
10.发送结果 | 驱动程序向Hive接口(CLI或者WebUI)发送结果 |
# Hive 服务器
HiveServer2(后面简称HS2)是从Hive 0.11版本开始引入的,它提供了一个服务器接口,允许客户端在Hive中执行查询并取回查询结果。当前的实现是一个HiveServer的改进版本,它基于Thrift RPC,支持多客户端身份认证和并发操作,其设计对JDBC、ODBC这样的开放API客户端提供了更好的支持。
HS2使用单一进程提供两种服务,分别是基于Thrift的Hive服务和一个Jetty Web服务器。基于Thrift的Hive服务是HS2的核心,它对Hive查询(例如从Beeline里发出的查询语句)做出响应。
Thrift是提供跨平台服务的RPC框架,允许客户端使用包括Java、C++、Ruby和其他很多语言,通过编程的方式远程访问Hive。它由服务器、传输、协议和处理器四层组成。
服务器。对于TCP请求,HS2使用Thrift中的TthreadPoolServer服务器提供响应,对于HTTP请求,会通过Jetty服务器做出响应。TThreadPoolServer会为每个TCP连接分配一个工作线程,该线程和相关的连接绑定在一起,即便是空连接也会分配一个线程。如果因并发连接过多使得线程数太大,会有潜在的性能问题。未来的HS2会可能为TCP请求提供其他类型的服务器,例如TThreadedSelectorServer。
传输。有TCP和HTTP两种传输模式。如果在客户端和服务器之间存在代理服务器(如因为负载均衡或安全方面的需要),那么只能通过HTTP模式访问Hive。这也就是HS2除了TCP方式外,还支持HTTP的原因。可以使用hive.server2.transport.mode配置参数指定Thrift服务的传输模式。
协议。协议的实现是为了进行序列化和反序列化。HS2当前使用TBinaryProtocol作为它的Thrift序列化协议。将来可能会基于性能评估考虑其他协议,如TCompactProtocol。
处理器。负责处理应用逻辑的请求,例如,ThriftCLIService.ExecuteStatement()方法实现编译和执行Hive查询的逻辑。
Hive通过Thrift提供Hive元数据存储的服务。通常来说,用户不能够调用元数据存储方法来直接对元数据进行修改,而应该通过HiveQL语言让Hive来执行这样的操作。用户应该只能通过只读方式来获取表的元数据信息。在5.6节我们配置了SparkSQL通过HS2服务访问Hive的元数据。
# 配置HS2
不同版本的HS2,配置属性可能会有所不同。最基本的配置是在hive-site.xml文件中设置如下属性:
- hive.server2.thrift.min.worker.threads:默认值是5,最小工作线程数。
- hive.server2.thrift.max.worker.threads:默认值是500,最大工作线程数。
- hive.server2.thrift.port:默认值是10000,监听的TCP端口号。
- hive.server2.thrift.bind.host:TCP接口绑定的主机。
除了在hive-site.xml配置文件中设置属性,还可以使用环境变量设置相关信息。环境变量的优先级别要高于配置文件,相同的属性如果在环境变量和配置文件中都有设置,则会使用环境变量的设置,就是说环境变量或覆盖掉配置文件里的设置。可以配置如下环境变量:
- HIVE_SERVER2_THRIFT_BIND_HOST:用于指定TCP接口绑定的主机。
- HIVE_SERVER2_THRIFT_PORT:指定监听的TCP端口号,默认值是10000。
HS2支持通过HTTP协议传输Thrift RPC消息(Hive 0.13以后的版本),这种方式特别用于支持客户端和服务器之间存在代理层的情况。当前HS2可以运行在TCP模式或HTTP模式下,但是不能同时使用两种模式。使用下面的属性设置启用HTTP模式:
- hive.server2.transport.mode:默认值是binary,设置为http启用HTTP传输模式。
- hive.server2.thrift.http.port:默认值是10001,监听的HTTP端口号。
- hive.server2.thrift.http.max.worker.threads:默认值是500,服务器池中的最大工作线程数。
- hive.server2.thrift.http.min.worker.threads:默认值是5,服务器池中的最小工作线程数。
可以配置hive.server2.global.init.file.location属性指定一个全局初始化文件的位置(Hive 0.14以后版本),它或者是初始化文件本身的路径,或者是一个名为“.hiverc”的文件所在的目录。在这个初始化文件中可以包含的一系列命令,这些命令会在HS2实例中运行,例如注册标准的JAR包或函数等。
如下参数配置HS2的操作日志:
- hive.server2.logging.operation.enabled:默认值是true,当设置为true时,HS2会保存对客户端的操作日志。
- hive.server2.logging.operation.log.location:默认值是${java.io.tmpdir}/${user.name}/operation_logs,指定存储操作日志的顶级目录。
- hive.server2.logging.operation.verbose:默认值是false,如果设置为true,HS2客户端将会打印详细信息。
- hive.server2.logging.operation.level:默认值是EXECUTION,该值允许在客户端的会话级进行设置。有四种日志级别,NONE忽略任何日志;EXECUTION记录完整的任务日志;PERFORMANCE在EXECUTION加上性能日志;VERBOSE记录全部日志。
默认情况下,HS2以连接服务器的用户的身份处理查询,但是如果将下面的属性设置为false,那么查询将以运行HS2进程的用户身份执行。当遇到无法创建临时表一类的错误时,可以尝试设置此属性:
- hive.server2.enable.doAs:作为连接用户的身份,默认值为true。
为了避免不安全的内存溢出,可以通过将以下参数设置为true,禁用文件系统缓存:
- fs.hdfs.impl.disable.cache:禁用HDFS缓存,默认值为false。
- fs.file.impl.disable.cache:禁用本地文件系统缓存,默认值为false。
# 启动HS2
下面两条命令都可以用于启动HS2:
$HIVE_HOME/bin/hiveserver2
$HIVE_HOME/bin/hive --service hiveserver2
2
# 临时目录管理
HS2允许配置临时目录,这些目录被Hive用于存储中间临时输出。临时目录相关的配置属性如下。
- hive.scratchdir.lock:默认值是false。如果设置为true,临时目录中会持有一个锁文件。如果一个Hive进程异常挂掉,可能会遗留下挂起的临时目录。使用cleardanglingscratchdir工具能够删除挂起的临时目录。如果此参数为false,则不会建立锁文件,cleardanglingscratchdir工具也不能删除任何挂起的临时目录。
- hive.exec.scratchdir:指定Hive作业使用的临时空间目录。该目录用于存储为查询产生的不同map/reduce阶段计划,也存储这些阶段的中间输出。
- hive.scratch.dir.permission:默认值是700。指定特定用户对根临时目录的权限。
- hive.start.cleanup.scratchdir:默认值是false。指定是否在启动HS2时清除临时目录。在多用户环境下不使用该属性,因为可能会删除正在使用的临时目录。
# HS2的Web用户界面(Hive2.0.0引入)
HS2的Web界面提供配置、日志、度量和活跃会话等信息,其使用的默认端口是10002。可以设置hive-site.xml文件中的hive.server2.webui.host、hive.server2.webui.port、hive.server2.webui.max.threads等属性配置Web接口。
# 查看Hive版本
Hive没有提供--version命令行参数或者version()函数的方式查看版本号。可以使用两种方法查看Hive版本。
(1)要找到Hive安装目录,然后查看jar包的版本号。
[root@cdh1~]#ls /opt/cloudera/parcels/CDH-5.7.0/lib/hive/lib | grep hwi
hive-hwi-1.1.0-cdh5.7.0.jar
hive-hwi.jar
[root@cdh1~]#
2
3
4
(2)查询元数据存储数据库的version表,例如从MySQL中执行的查询和结果如下。
select * from hive.version;
# 三、数据类型
# 3.1 基本数据类型
Hive 表中的列支持以下基本数据类型:
大类 | 类型 |
---|---|
Integers(整型) | TINYINT—1 字节的有符号整数 SMALLINT—2 字节的有符号整数 INT—4 字节的有符号整数 BIGINT—8 字节的有符号整数 |
Boolean(布尔型) | BOOLEAN—TRUE/FALSE |
Floating point numbers(浮点型) | FLOAT— 单精度浮点型 DOUBLE—双精度浮点型 |
Fixed point numbers(定点数) | DECIMAL—用户自定义精度定点数,比如 DECIMAL(7,2) |
String types(字符串) | STRING—指定字符集的字符序列 VARCHAR—具有最大长度限制的字符序列 CHAR—固定长度的字符序列 |
Date and time types(日期时间类型) | TIMESTAMP — 时间戳 TIMESTAMP WITH LOCAL TIME ZONE — 时间戳,纳秒精度 DATE—日期类型 |
Binary types(二进制类型) | BINARY—字节序列 |
TIMESTAMP 和 TIMESTAMP WITH LOCAL TIME ZONE 的区别如下:
- TIMESTAMP WITH LOCAL TIME ZONE:用户提交时间给数据库时,会被转换成数据库所在的时区来保存。查询时则按照查询客户端的不同,转换为查询客户端所在时区的时间。
- TIMESTAMP :提交什么时间就保存什么时间,查询时也不做任何转换。
# 3.2 隐式转换
Hive 中基本数据类型遵循以下的层次结构,按照这个层次结构,子类型到祖先类型允许隐式转换。例如 INT 类型的数据允许隐式转换为 BIGINT 类型。额外注意的是:按照类型层次结构允许将 STRING 类型隐式转换为 DOUBLE 类型。
# 3.3 复杂类型
类型 | 描述 | 示例 |
---|---|---|
STRUCT | 类似于对象,是字段的集合,字段的类型可以不同,可以使用 名称.字段名 方式进行访问 | STRUCT ('xiaoming', 12 , '2018-12-12') |
MAP | 键值对的集合,可以使用 名称[key] 的方式访问对应的值 | map('a', 1, 'b', 2) |
ARRAY | 数组是一组具有相同类型和名称的变量的集合,可以使用 名称[index] 访问对应的值 | ARRAY('a', 'b', 'c', 'd') |
# 3.4 示例
如下给出一个基本数据类型和复杂数据类型的使用示例:
CREATE TABLE students(
name STRING, -- 姓名
age INT, -- 年龄
subject ARRAY<STRING>, --学科
score MAP<STRING,FLOAT>, --各个学科考试成绩
address STRUCT<houseNumber:int, street:STRING, city:STRING, province:STRING> --家庭居住地址
) ROW FORMAT DELIMITED FIELDS TERMINATED BY "\t";
2
3
4
5
6
7
# 四、内容格式
当数据存储在文本文件中,必须按照一定格式区别行和列,如使用逗号作为分隔符的 CSV 文件 (Comma-Separated Values) 或者使用制表符作为分隔值的 TSV 文件 (Tab-Separated Values)。但此时也存在一个缺点,就是正常的文件内容中也可能出现逗号或者制表符。
所以 Hive 默认使用了几个平时很少出现的字符,这些字符一般不会作为内容出现在文件中。Hive 默认的行和列分隔符如下表所示。
分隔符 | 描述 |
---|---|
\n | 对于文本文件来说,每行是一条记录,所以可以使用换行符来分割记录 |
^A (Ctrl+A) | 分割字段 (列),在 CREATE TABLE 语句中也可以使用八进制编码 \001 来表示 |
^B | 用于分割 ARRAY 或者 STRUCT 中的元素,或者用于 MAP 中键值对之间的分割, 在 CREATE TABLE 语句中也可以使用八进制编码 \002 表示 |
^C | 用于 MAP 中键和值之间的分割,在 CREATE TABLE 语句中也可以使用八进制编码 \003 表示 |
使用示例如下:
CREATE TABLE page_view(viewTime INT, userid BIGINT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
STORED AS SEQUENCEFILE;
2
3
4
5
6
# 五、存储格式
# 5.1 支持的存储格式
Hive 会在 HDFS 为每个数据库上创建一个目录,数据库中的表是该目录的子目录,表中的数据会以文件的形式存储在对应的表目录下。Hive 支持以下几种文件存储格式:
格式 | 说明 |
---|---|
TextFile | 存储为纯文本文件。 这是 Hive 默认的文件存储格式。这种存储方式数据不做压缩,磁盘开销大,数据解析开销大。 |
SequenceFile | SequenceFile 是 Hadoop API 提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中。这种二进制文件内部使用 Hadoop 的标准的 Writable 接口实现序列化和反序列化。它与 Hadoop API 中的 MapFile 是互相兼容的。Hive 中的 SequenceFile 继承自 Hadoop API 的 SequenceFile,不过它的 key 为空,使用 value 存放实际的值,这样是为了避免 MR 在运行 map 阶段进行额外的排序操作。 |
RCFile | RCFile 文件格式是 FaceBook 开源的一种 Hive 的文件存储格式,首先将表分为几个行组,对每个行组内的数据按列存储,每一列的数据都是分开存储。 |
ORC Files | ORC 是在一定程度上扩展了 RCFile,是对 RCFile 的优化。 |
Avro Files | Avro 是一个数据序列化系统,设计用于支持大批量数据交换的应用。它的主要特点有:支持二进制序列化方式,可以便捷,快速地处理大量数据;动态语言友好,Avro 提供的机制使动态语言可以方便地处理 Avro 数据。 |
Parquet | Parquet 是基于 Dremel 的数据模型和算法实现的,面向分析型业务的列式存储格式。它通过按列进行高效压缩和特殊的编码技术,从而在降低存储空间的同时提高了 IO 效率。 |
以上压缩格式中 ORC 和 Parquet 的综合性能突出,使用较为广泛,推荐使用这两种格式。 我也做过SequenceFile和ORC File的,压缩和执行测试 Sequence Files VS ORC Files (opens new window)
# 5.2 指定存储格式
通常在创建表的时候使用 STORED AS
参数指定:
CREATE TABLE page_view(viewTime INT, userid BIGINT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\001'
COLLECTION ITEMS TERMINATED BY '\002'
MAP KEYS TERMINATED BY '\003'
STORED AS SEQUENCEFILE;
2
3
4
5
6
各个存储文件类型指定方式如下:
- STORED AS TEXTFILE
- STORED AS SEQUENCEFILE
- STORED AS ORC
- STORED AS PARQUET
- STORED AS AVRO
- STORED AS RCFILE
# 六、内部表和外部表
内部表又叫做管理表 (Managed/Internal Table),创建表时不做任何指定,默认创建的就是内部表。想要创建外部表 (External Table),则需要使用 External 进行修饰。 内部表和外部表主要区别如下:
内部表 | 外部表 | |
---|---|---|
数据存储位置 | 内部表数据存储的位置由 hive.metastore.warehouse.dir 参数指定,默认情况下表的数据存储在 HDFS 的 /user/hive/warehouse/数据库名.db/表名/ 目录下 | 外部表数据的存储位置创建表时由 Location 参数指定; |
导入数据 | 在导入数据到内部表,内部表将数据移动到自己的数据仓库目录下,数据的生命周期由 Hive 来进行管理 | 外部表不会将数据移动到自己的数据仓库目录下,只是在元数据中存储了数据的位置 |
删除表 | 删除元数据(metadata)和文件 | 只删除元数据(metadata) |
# Hive客户端
Hive最初的形式是一个重量级的命令行工具,它接收查询指令并利用MapReduce执行查询。后来Hive采用了客户端-服务器模式,HiveServer(简称HS1)作为服务器端,负责将查询语句编译成MapReduce作业,并监控它们的执行。而Hive CLI(hive shell命令)是一个命令行接口,负责接收用户的HiveQL语句,并传送到服务器。 Hive社区在0.11版中引入了HS2,并推荐使用新的Beeline命令行接口(beeline shell命令),HS1及其Hive CLI不再建议使用,甚至过时的Hive CLI客户端方案以后可能将不能与HS2一起使用。下面重点介绍Beeline客户端,在本小节最后说明Hive CLI和Beeline用法上的主要差别。
Beeline是为与新的Hive服务器进行交互而特别开发的。与Hive CLI不同,Beeline不是基于Thrift的客户端,而是一个基于SQLLine CLI的JDBC客户端,尽管用于和HS2通信的JDBC驱动程序还是使用的Thrift API。Beeline有嵌入和远程两种操作模式。在嵌入模式中,它运行一个嵌入的类似于hive的shell命令;而在远程模式中,它通过Thrift服务连接一个分离的HS2进程。从Hive 0.14开始,当Beeline与HS2联合使用时,还会在交互式查询中打印很长的HS2消息信息。生产系统推荐使用远程HS2模式,因为它更安全,不需要授予用户直接访问HDFS或元数据存储的权限。
# Beeline命令
$HIVE_HOME/bin/beeline这个shell命令(后面简称为beeline)用于连接Hive服务器。假定已经将$HIVE_HOME/bin加入到环境变量PATH中,则只需要在shell提示符中输入beeline
,就可以使用户的shell环境如bash找到这个命令。\
# 进入Beeline后链接服务器
beeline > !connect jdbc:hive2://cdh2:10000
2
也可以在命令行直接指定连接参数。这意味着能够在Linux shell的命令历史history中找到含有连接字符串的beeline命令。
beeline -u jdbc:hive2://cdh2:10000/test
# 连接URL
Beeline客户端使用URL格式连接Hive数据库,HS2的URL连接字符串语法如下:
jdbc:hive2://<host1>:<port1>,<host2>:<port2>/dbName;initFile=<file>;sess_var_list?hive_conf_l ist#hive_var_list
<host1>:<port1>,<host2>:<port2>
:要连接的一个服务器实例,或者是用逗号分隔的多个服务器实例,如果为空,将使用嵌入模式。- dbName:初始连接的数据库名称。
<file>
:初始化脚本的路径(Hive 2.2.0及以后版本支持)。这个脚本文件中的HiveQL语句会在连接后自动执行。该选项可以为空。sess_var_list
:以一个逗号分隔的、会话级变量的键/值对列表。hive_conf_list
:以一个逗号分隔的、Hive配置变量的键/值对列表。hive_var_list
:以一个逗号分隔的、Hive变量的键/值对列表。
JDBC连接具有jdbc:hive2://前缀,驱动的类是org.apache.hive.jdbc.HiveDriver。注意这和老的HS1不同。
对于远程连接模式,连接URL的格式为:
jdbc:hive2://<host>:<port>/<db>;initFile=<file>(HS2 默认的端口是 10000)。
对于嵌入连接模式,连接URL的格式为:
jdbc:hive2:///;initFile=<file>(没有主机名和端口)。
当HS2以HTTP模式运行时,连接URL的格式为:
jdbc:hive2://<host>:<port>/<db>;transportMode=http;httpPath=<http_endpoint>,其中 <http_endpoint>对应的是hive-site.xml文件中配置hive.server2.thrift.http.path 属性值,默认值为 cliservice。默认的HTTP传输端口为10001。
当HS2启用了SSL时,连接URL的格式为:
jdbc:hive2://<host>:<port>/<db>;ssl=true;sslTrustStore=<trust_store_path>;trustStorePassword= <trust_store_password>
其中<trust_store_path>
是客户端信任文件所在路径,<trust_store_password>
是访问信任文件所需的密码。相应HTTP模式的格式为:
jdbc:hive2://<host>:<port>/<db>;ssl=true;sslTrustStore=<trust_store_path>;trustStorePassword= <trust_store_password>;transportMode=http;httpPath=<http_endpoint>。
从Hive 2.1.0开始,Beeline支持命名URL连接串,这是通过环境变量实现的。如果使用!connect连接一个名称,而不是URL,那么Beeline会查找一个名为BEELINE_URL_<name>
的环境变量。例如,如果命令为!connect blue,Beeline会查找BEELINE_URL_BLUE环境变量,并使用该变量的值做连接。对于系统管理员来说,为用户设置环境变量相对方便些,用户也不需要在每次连接时都键入完整的URL字符串。 !reconnect命令用于刷新已经建立的连接,如果已经执行!close命令关闭了连接,则不能再刷新连接。从Hive 2.1.0起,Beeline会记住一个会话最后成功连接的URL,这样即使已经运行了!close命令也能够重连。另外,如果用户执行了!save命令,连接会被保存到beeline.properties文件中,当执行!reconnect时,会连接到这个保存的URL。也可以在命令行使用-r参数,在启动Beeline时执行重连操作。
# 变量和属性
--hivevar参数可以让用户在命令行定义自己的变量以便在Hive脚本中引用,以满足不同情况的需要。这个功能只有Hive 0.8.0及其之后版本才支持。当使用这个功能时,Hive会将键/值对放到hivevar命名空间,这样就能和另外三种内置的命名空间(hiveconf、system和env)加以区分。下表描述了Hive的4种命名空间选项。
命名空间 | 使用权限 | 描述 |
---|---|---|
hivevar | 可读写 | 用户自定义变量(Hive 0.8.0及以后版本) |
hiveconf | 可读写 | Hive相关的配置属性 |
system | 可读写 | Java定义的配置属性 |
Env | 只读 | shell环境(如bash)定义的环境变量 |
变量在Hive内部是以Java字符串的方式存储的。用户可以在查询中引用变量。Hive会先使用变量值替换掉查询的变量引用,然后才会将查询语句提交给查询处理器。在beeline环境中,可以使用set命令显示或者修改变量值。例如,下面这个会话先显示一个env变量的值,然后再显示所有命名空间中定义的变量。为了更清晰地表现,我们省略掉这个Hive会话中大量的输出信息:
set env:HOME;
set;
set -v;
2
3
如果不加-v标记,set命令会打印出hivevar、hiveconf、system和env中所有的变量。使用-v标记,则会打印出Hadoop中所定义的所有属性。例如控制HDFS和MapReduce的属性。set命令还可用于给变量赋新的值。我们特别看下hivevar命名空间以及如何通过命令行定义一个变量:
beeline --hivevar foo=bar
0: jdbc:hive2://bihell:10000/default> set foo;
+----------+--+
| set |
+----------+--+
| foo=bar |
+----------+--+
1 row selected (6.41 seconds)
0: jdbc:hive2://bihell:10000/default> set hivevar:foo;
+-------------------+--+
| set |
+-------------------+--+
| hivevar:foo=bar2 |
+-------------------+--+
1 row selected (0.005 seconds)
0: jdbc:hive2://bihell:10000/default> set foo;
+-----------+--+
| set |
+-----------+--+
| foo=bar2 |
+-----------+--+
1 row selected (0.005 seconds)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
可以看到,前缀hivevar:是可选的,如果不加前缀,默认的命名空间就是hivevar。在beeline环境中,查询语句的变量引用会先被替换掉,然后才提交给查询处理器。
0: jdbc:hive2://bihell:10000/default> create table bihell(i int,${hivevar:foo} string);
+-----------+------------+----------+--+
| col_name | data_type | comment |
+-----------+------------+----------+--+
| i | int | |
| bar2 | string | |
+-----------+------------+----------+--+
0: jdbc:hive2://bihell:10000/default> create table bihell2 (i int,${foo} string);
+-----------+------------+----------+--+
| col_name | data_type | comment |
+-----------+------------+----------+--+
| i | int | |
| bar2 | string | |
+-----------+------------+----------+--+
2
3
4
5
6
7
8
9
10
11
12
13
14
15
--hiveconf选项是hive 0.7版本后支持的功能,用于配置Hive行为的所有属性。我们甚至可以增加新的hiveconf属性。
0: jdbc:hive2://bihell:10000/default> set hiveconf:y=1;
No rows affected (0.002 seconds)
0: jdbc:hive2://bihell:10000/default> set hiveconf:y;
+---------------+--+
| set |
+---------------+--+
| hiveconf:y=1 |
+---------------+--+
1 row selected (0.005 seconds)
0: jdbc:hive2://bihell:10000/default> select * from t where id=${hiveconf:y);
2
3
4
5
6
7
8
9
10
运行指定文件中的SQL
beeline -u "jdbc:hive2://xxx.xxx.com:10000" --hiveconf rptdate=`date --date='1 days ago' "+%Y%m%d"` -n hdfs -f /xx/xx/xx.SQL
# --hiveconf rptdate用来把变量带入SQL脚本,SQL脚本中使用${hiveconf:rptdate}获变量值。
2
我们还有必要了解一下system命名空间,它定义Java系统属性。Beeline对这个命名空间内容具有可读写权利,而对于env命名空间的环境变量只提供读权限。
0: jdbc:hive2://bihell:10000/default> set ststem:user.name;
+--------------------------------+--+
| set |
+--------------------------------+--+
| ststem:user.name is undefined |
+--------------------------------+--+
1 row selected (0.005 seconds)
0: jdbc:hive2://bihell:10000/default> set system:user.name;
+------------------------+--+
| set |
+------------------------+--+
| system:user.name=hive |
+------------------------+--+
1 row selected (0.006 seconds)
0: jdbc:hive2://bihell:10000/default> set system:user.name=hive2;
No rows affected (0.007 seconds)
0: jdbc:hive2://bihell:10000/default> set system:user.name;
+-------------------------+--+
| set |
+-------------------------+--+
| system:user.name=hive2 |
+-------------------------+--+
1 row selected (0.005 seconds)
0: jdbc:hive2://bihell:10000/default> set env:HOME;
+-------------------------+--+
| set |
+-------------------------+--+
| env:HOME=/var/lib/hive |
+-------------------------+--+
1 row selected (0.005 seconds)
0: jdbc:hive2://bihell:10000/default> set env:HOME=/var/lib/hive2;
Error: Error while processing statement: null (state=,code=1)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
和hivevar变量不同,用户必须使用system:或者env:前缀来指定系统属性和环境变量。env命名空间可作为向Hive传递变量的一个可选的方式。
YEAR=2020
beeline -u jdbc:hive2://bihell:10000/test -e "select * from t where yar = ${env:YEAR}";
2
查询处理器会在where子句中查看到实际的变量值为2020。Hive中所有的内置属性都在$HIVE_HOME/conf/hive-default.xml.template文件中列举出来了,这是个样例配置文件,其中还说明了这些属性的默认值。
# 输出格式
在Beeline中,查询结果能以不同的格式显示出来。显示格式可以通过outputformat选项设置。支持的输出格式有table、vertical、xmlattr、xmlelements和分隔值格式(csv、tsv、csv2、tsv2、dsv)。以下是一些不同格式的输出示例。
# Hive CLI和Beeline使用上的主要差别
随着Hive从原始的HS1服务器进化为新的HS2,用户和开发者也需要将客户端工具从原来的Hive CLI切换为新的Beeline,然而这种切换并不只是将“hive”命令换成“beeline”命令这么简单。下面介绍两种客户端用法上的主要差异。
- Hive CLI提供了一个可以打印RCFile格式文件内容的工具,如:
hive --service rcfilecat /user/hive/warehouse/columntable/000000_0
Beeline没有此项功能。 - Hive CLI可以使用source命令来执行脚本文件,如:
hive> source /path/to/file/queries.hql;
Beeline没有此项功能。 - Hive CLI可以配置hive.cli.print.current.db属性,在命令行提示符前打印当前数据库名,如:
$hive -hiveconf hive.cli.print.current.db=true
。Beeline使用--showDbInPrompt命令行参数实现此功能(2.2.0版本新增)。 - Hive CLI可以使用“!”操作符执行shell命令,如
hive> ! pwd;
Beeline中不能执行shell命令,其中的“!”符号是用来执行Beeline命令的,如:beeline> !connect jdbc:hive2://cdh2:10000
- Hive CLI中,默认时在查询结果中不显示字段名称,需要设置hive.cli.print.header选项打印字段名称,如:
hive> set hive.cli.print.header=true;
而Beeline不需要此项设置就会在输出中显示字段名称。 - Hive CLI中可以使用--define命令行参数设置变量,它和--hivevar是相同的,如:
hive --define foo=bar
而在Beeline中--define参数是无效的,只能使用--hivevar参数。 - Hive CLI可以使用-S选项开启静默模式,这样可以在输出结果中去掉额外的输出信息,而Beeline虽然提供了-silent参数,似乎能起到相同的效果,但实际上不行(至少在CDH 5.7.0上,该参数和hive的-S作用是不同的)。
- Hive CLI支持管道符。例如,用户没有记清楚哪个属性指定了管理表的“warehouse”路径,通过如下的命令可以查看到:
hive -e "set" | grep warehouse
上面的命令换成beeline则不会得到想要的结果。Beeline需要在客户端脚本中添加设置支持事务的set命令,即使在服务器端的hivesite.xml文件中已经设置,而Hive CLI则不需要。
常用DDL操作 →