# 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
1
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~]#
1
2
3
4

(2)查询元数据存储数据库的version表,例如从MySQL中执行的查询和结果如下。

select * from hive.version;
1

# 三、数据类型

# 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";
1
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;
1
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;
1
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
1
2

也可以在命令行直接指定连接参数。这意味着能够在Linux shell的命令历史history中找到含有连接字符串的beeline命令。

beeline -u jdbc:hive2://cdh2:10000/test
1

# 连接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;
1
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)
1
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     |          |
+-----------+------------+----------+--+
1
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);
1
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}获变量值。
1
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)
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}";
1
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则不需要。
更新时间: 4/17/2020, 2:47:47 PM