Hive入门

1 定义

是构建于Hadoop上的数据仓库,用于查询和分析。为了避免底层Java API,使用类似SQL的HQL查询。HQL将查询转换为MapReduce、Apache Tez或Spark作业。

(1) 特性

  • 索引:包括压缩和bitmap索引
  • 多种存储类型,如文本、HBase等
  • 存储元数据到关系型数据库中,有效减少查询时的语义检查
  • 操作压缩的数据,如使用算法DEFALTE、snnapy等
  • 支持标准SQL, user defined functions (UDFs), user defined aggregates (UDAFs),和user defined table functions (UDTFs)
  • 使用HQL进行ETL、报表和分析,将HQL转换为作业
  • 通过 Hive LLAP, Apache YARNApache Slider实现亚秒级查询

默认使用Derby数据库存储元数据。

不是为OLTP设计的

Hive最大化伸缩性、性能、扩展性、容错、输入格式松散耦合。

(2) 组件

包括HCatalog和WebHcat。

  • HCatalog

    用于Hadoop的表格和存储管理层,用于使用多种数据处理工具,如Pig和MapReduce。

  • WebHCat

    提供运行作业的服务,并且可以使用REST API操作元数据

2 安装和配置

(1) 要求

  • Java 1.7(>=1.2)

  • Hadoop 2.x (>=2.0.0)

  • Linux/Windows(生产环境)、Mac(开发环境)

需要配置环境变量HIVE_HOME

(2) 运行

1) 前提

  • 配置HADOOP_HOME
  • 创建HDFS目录/tmp和/user/hive/warehouse(hive.metastore.warehouse.dir中定义),并赋予权限chmod g+w
1
2
3
4
$ $HADOOP_HOME/bin/hadoop fs -mkdir       /tmp
$ $HADOOP_HOME/bin/hadoop fs -mkdir /user/hive/warehouse
$ $HADOOP_HOME/bin/hadoop fs -chmod g+w /tmp
$ $HADOOP_HOME/bin/hadoop fs -chmod g+w /user/hive/warehouse

2) 运行HiveServer2和Beeline

从版本2.1开始,需要使用schematool初始化数据库类型

1
$ $HIVE_HOME/bin/schematool -dbType <db type> -initSchema

启动HiveServer2和Beeline(HiveServer2自带CLI)。由于缺乏多用户和安全等能力,HiveCLI已标记弃用。

1
2
3
4
$ $HIVE_HOME/bin/hiveserver2

## 默认主机端口为localhost:10000
$ $HIVE_HOME/bin/beeline -u jdbc:hive2://$HS2_HOST:$HS2_PORT

3) 运行HCatalog

从版本0.11.0开始,详见HCatalog manual

1
2
3
4
5
6
7
// 启动服务器端
$ $HIVE_HOME/hcatalog/sbin/hcat_server.sh start
// 关闭
$ $HIVE_HOME/hcatalog/sbin/hcat_server.sh stop

// 使用命令行
$ $HIVE_HOME/hcatalog/bin/hcat

4) 启动WebHCat

从版本0.11.0开始,详见WebHCat Installation

1
2
3
4
5
// 启动
$ $HIVE_HOME/hcatalog/sbin/webhcat_server.sh start

// 关闭
$ $HIVE_HOME/hcatalog/sbin/webhcat_server.sh stop

3 配置管理概览

默认配置位置: <install-dir>/conf/hive-default.xml

配置目录设置:HIVE_CONF_DIR

配置变更:<install-dir>/conf/hive-site.xml

Log4J配置:<install-dir>/conf/hive-log4j.properties

Hive配置继承了Hadoop的配置,可以在Hive中设置Hadoop配置

配置操作:

  • 编辑hive-site.xml,可设置Hadoop配置

  • 使用set命令

  • 调用Beeline或HiveServer2:

    1
    2
    $ bin/hiveserver2 --hiveconf x1=y1 --hiveconf x2=y2  //this sets server-side variables x1 and x2 to y1 and y2 respectively
    $ bin/beeline --hiveconf x1=y1 --hiveconf x2=y2 //this sets client-side variables x1 and x2 to y1 and y2 respectively.
  • 设置HIVE_OPTS环境变量

    1
    --hiveconf x1=y1 --hiveconf x2=y2

4 运行时配置

由于Hive查询使用mapReduce执行,查询的行为可以有Hadoop配置

Beeline的SET命令可以设置Hive或Hadoop配置变量。如:

1
2
3
4
5
beeline> SET mapred.job.tracker=myhost.mycompany.com:50030;

// 展示当前配置
// 不带-v将只展示与Hadoop不同的配置
beeline> SET -v;

5 Hive、MapReduce和本地模式

集群执行时,指定集群:cd

对于小数据集,本地执行更加高效。

版本>=0.7,Hive完全支持本地执行。

1
2
// 开启本地执行
hive> SET mapreduce.framework.name=local;

注意:mapred.local.dir需要在本地可用

版本>=0.7,Hive支持根据作业自动切换本地执行。

1
2
// 自动切换本地执行,默认关闭
hive> SET hive.exec.mode.local.auto=false;

切换本地执行,需要满足以下条件:

  • 作业输入数据量小于hive.exec.mode.local.auto.inputbytes.max(默认128MB)
  • map任务数小于hive.exec.mode.local.auto.tasks.max(默认4个)
  • reduce任务数不大于1个

注意:

节点本地环境不同,可能导致出错。

本地进程以Hive client子进程的形式进行,内存上限默认由Hadoop决定,可通过hive.mapred.local.mem修改。

6 日志

Hive使用log4j记录日志。

默认不在控制台输出。

版本>=0.13,默认的日志级别为INFO。默认的日志输出文件为/tmp/<user.name>/hive.log,可通过 $HIVE_HOME/conf/hive-log4j.properties中的hive.log.dir变量配置,需要设置权限chmod 1777 <dir>

1
2
3
4
5
6
7
8
// 输出控制台
bin/hiveserver2 --hiveconf hive.root.logger=INFO,console

// 修改日志级别(only)
bin/hiveserver2 --hiveconf hive.root.logger=INFO,DRFA

// 版本>= 1.1.0, 设置时间滚动策略
bin/hiveserver2 --hiveconf hive.root.logger=INFO,DAILY

注意:hive.root.logger仅在初始化时生效,不影响配置文件

Hive为每个会话存储查询日志到/tmp//,可通过hive-site.xmlhive.querylog.location配置。版本>=1.1.0,EXPLAIN EXTENDED可以通过设置hive.log.explain.output为true,更改为INFO级别。

集群执行时,Hadoop为每个任务生成日志,可通过Web UI获取。

本地执行时,Hive为每次查询生成一个日志文件,默认输出到/tmp//。版本>=0.6,使用hive-exec-log4j.properties(前者不存在时,使用 hive-log4j.properties)设置输出目录。分离的配置允许使用网络存储设备,如NFS。

WebHCat日志和错误,详见Error Codes and ResponsesLog Files

版本>= 2.1.0,Hive使用Log4j2的异步日志,其通过独立的日志线程,并且使用LMAX disruptor队列缓存,提高性能。可以通过hive.async.log.enabled设置开关。

(1) HiveServer2 日志

版本>=0.14可用,详见HiveServer2 Logging

(2) Audit日志

记录Hive元数据服务器中的每次元数据API调用。

由于使用INFO级别,需要保证日志输出级别为INFO。

日志入口为HiveMetaStore.audit

版本>=0.7提供安全客户端连接,版本>=0.10提供非安全连接。

(3) 性能日志记录器

用于性能测量。

若hive.root.logger不是DEBUG级别,需要设置PrefLogger为DEBUG级别:

1
log4j.logger.org.apache.hadoop.hive.ql.log.PerfLogger=DEBUG

7 DDL操作

详见Hive Data Definition Language

(1) 创建表

1
2
3
4
5
hive> CREATE TABLE pokes (foo INT, bar STRING);

// 创建名为invites的表。具有两列(整型foo和字符串bar)。
// 分区列是从数据中提取的虚拟列
hive> CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING);

默认,数据以文本格式录入表,使用^A(ctrl-a)分隔。

(2) 检索表

1
2
3
4
5
6
7
8
// 列举所有表
hive> SHOW TABLES;

// 列举匹配正则表达式的表
hive> SHOW TABLES '.*s';

// 列举表格所有列
hive> DESCRIBE invites;

正则语法详见Java regular expressions

(3) 修改、删除表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 表更名
hive> ALTER TABLE events RENAME TO 3koobecaf;

// 增加列
hive> ALTER TABLE pokes ADD COLUMNS (new_col INT);
hive> ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment');

// 列更名,只是改动schema,不涉及数据
// 表必须使用本地序列化与反序列化(简称,SerDe)
hive> ALTER TABLE invites REPLACE COLUMNS (foo INT, bar STRING, baz INT COMMENT 'baz replaces new_col2');

// 列删除
// 只保留第一列
hive> ALTER TABLE invites REPLACE COLUMNS (foo INT COMMENT 'only keep the first column');

// 表删除
hive> DROP TABLE pokes;

(4) 元数据存储

元数据保存在内嵌的Derby数据库中。

元数据可以存储在支持JPOX的数据库中。通过变量javax.jdo.option.ConnectionURL和javax.jdo.option.ConnectionDriverName配置位置和类型。

数据库Schema保存在src/contrib/hive/metastore/src/model/package.jdo的JDO元数据注解中。

默认存储位置为./metastore_db (详见conf/hive-default.xml),可通过javax.jdo.option.ConnectionURL变量修改。

默认配置,同一时刻只对一个用户可见。

以网络服务器形式运行元数据存储,详见Hive Using Derby in Server Mode

TODO, 元数据存储实现为standalone服务器。

注释:JPOX是JDO(Java Data Object)的一个实现。提供Java对象透明的一致性,支持OLAP和RDBMS。

4 DML操作

详见Hive Data Manipulation Language

1
2
// 加载本地文件到表中
hive> LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes;

LOCAL:本地文件。若缺省,为HDFS文件

OVERWRITE:删除已有数据。若缺省,为追加

注意:

加载命令不检查数据schema

加载HDFS文件,将移动文件或文件夹到Hive路径下。建议先创建路径。通过hive-default.xml中hive.metastore.warehouse.dir变量控制。

1
2
3
4
// 只有定义了分区列的表才能使用分区
hive> LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');
//移动HDFS文件几乎是瞬时的
hive> LOAD DATA INPATH '/user/myname/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15');

5 SQL操作

详见Select

示例详见build/dist/examples/queries和ql/src/test/queries/positive。

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
// 查询,结果在控制台输出,不另存
hive> SELECT a.foo FROM invites a WHERE a.ds='2008-08-15';

// 插入数据到HDFS中,结果存储在指定目录下的文件中(数量依据mapper数量)
// 分区的表必须有分区条件限制,否则全部分区检索
hive> INSERT OVERWRITE DIRECTORY '/tmp/hdfs_out' SELECT a.* FROM invites a WHERE a.ds='2008-08-15';
hive> INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' SELECT a.* FROM pokes a;
hive> INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a WHERE a.key < 100;

// GROUP BY
hive> FROM invites a INSERT OVERWRITE TABLE events SELECT a.bar, count(*) WHERE a.foo > 0 GROUP BY a.bar;
hive> INSERT OVERWRITE TABLE events SELECT a.bar, count(*) FROM invites a WHERE a.foo > 0 GROUP BY a.bar;

// JOIN
hive> FROM pokes t1 JOIN invites t2 ON (t1.bar = t2.bar) INSERT OVERWRITE TABLE events SELECT t1.bar, t1.foo, t2.foo;

// MultiTable Insert
FROM src
INSERT OVERWRITE TABLE dest1 SELECT src.* WHERE src.key < 100
INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key >= 100 and src.key < 200
INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300;

// Streaming
// 在map阶段通过/bin/cat脚本转换数据。也可以在reduce阶段
hive> FROM invites a INSERT OVERWRITE TABLE events SELECT TRANSFORM(a.foo, a.bar) AS (oof, rab) USING '/bin/cat' WHERE a.ds > '2008-08-09';

注意: 版本< 0.6(不包含HIVE-287的版本),使用count(1)代替count(*)

Streaming详见Hive Tutorial

6 采坑指南

(1) 使用schematool初始化数据库类型时

报错:

1
java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang/String;Ljava/lang/Object;)V

通过查阅资料,可能是Hadoop与Hive中Guava版本不一致引起,需要删除Hive中的jar包。同样对于log4j-slf4j-impl-2.10.0.jar。并从hadoop中拷贝。

1
2
3
cd apache-hive-3.1.2-bin/lib/;rm guava-19.0.jar;rm log4j-slf4j-impl-2.10.0.jar

cp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/guava-27.0-jre.jar /home/nick/apache-hive-3.1.2-bin/lib;scp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/guava-27.0-jre.jar nick@slave1:/home/nick/apache-hive-3.1.2-bin/lib;scp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/guava-27.0-jre.jar nick@slave2:/home/nick/apache-hive-3.1.2-bin/lib;scp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/guava-27.0-jre.jar nick@slave3:/home/nick/apache-hive-3.1.2-bin/lib;cp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/log4j-1.2.17.jar /home/nick/apache-hive-3.1.2-bin/lib;scp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/log4j-1.2.17.jar nick@slave1:/home/nick/apache-hive-3.1.2-bin/lib;scp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/log4j-1.2.17.jar nick@slave2:/home/nick/apache-hive-3.1.2-bin/lib;scp /home/nick/hadoop-3.2.1/share/hadoop/common/lib/log4j-1.2.17.jar nick@slave3:/home/nick/apache-hive-3.1.2-bin/lib;

启动HCatalog时,报错/home/nick/apache-hive-3.1.2-bin/hcatalog/sbin/hcat_server.sh:行91: /home/nick/apache-hive-3.1.2-bin/hcatalog/sbin/../var/log/hcat.out: 没有那个文件或目录;

解决:创建该文件

beeline中创建数据库时,报错Error: Error while processing statement: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. MetaException(message:Got exception: org.apache.hadoop.security.AccessControlException Permission denied: user=anonymous, access=WRITE, inode=”/user/nick/warehouse”:nick:supergroup:drwxrwxr-x;

解决:赋予写权限

beeline查询表时,报错: Execution Error, return code 30041 from org.apache.hadoop.hive.ql.exec.spark.SparkTask. Failed to create Spark client for Spark session 1ee619c9-e587-4577-a03c-c9ef5f6eedb2 (state=42000,code=30041)

解决:

Spark 2.0.0已经标记弃用hive.metastore.warehouse.dirproperty inhive-site.xml,改为使用spark.sql.warehouse.dir指示数据仓库中默认数据库位置。

1
2
3
4
5
<property>
<name>spark.sql.warehouse.dir</name>
<value>/user/nick/warehouse</value>
<description>same with hive.metastore.warehouse.dir, which is deprecated in 2.0.0</description>
</property>

复制hive-site.xml, core-site.xml (for security configuration), and hdfs-site.xml (for HDFS configuration) file in conf/,然后启动Spark集群。

beeline查询表时,报错 Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.spark.SparkTask. Spark job failed during runtime. Please check stacktrace for the root cause. (state=42000,code=2)

过程:需要日志查看细节hive –hiveconf hive.root.logger=DEBUG,console

找到链接http://master:8088/cluster/app/application_1592471815985_0004

其中抛出异常:找不到或无法加载主类 org.apache.spark.deploy.yarn.ExecutorLauncher

查阅资料,怀疑问题在没有让Spark访问到类,需要在spark-defaults.conf中设置spark.yarn.jars hdfs://master:8020/spark-jars/*

原因:配置中HDFS路径问题导致jar没找到

解决:不能使用beeline操作,待探究

需要使用hive命令操作,可行

启动spark history server时报错

java.io.FileNotFoundException: Log directory specified does not exist: file:/tmp/spark-events Did you configure the correct one through spark.history.fs.logDirectory?

在spark-env.sh中设置 spark.history.fs.logDirectory用于在应用执行后保存日志

1
export SPARK_HISTORY_OPTS="-Dspark.history.ui.port=18080 -Dspark.history.retainedApplications=20 -Dspark.history.fs.logDirectory=hdfs://master:8020/spark-log"

启动spark history server时报错,目录找不到

解决:HDFS目录中默认前缀为/user/nick,需要在配置中显式添加,否则不能找到。待探究去除的情况

参考资料

Apache Hive

Home

Hive Tutorial

Hive学习之路 (一)Hive初识

GettingStarted

启动hive报错:java.lang.NoSuchMethodError: com.google.common.base.Preconditions.checkArgument(ZLjava/lang

hive bin下的进入beeline 命令行和hive有什么不同?

hive启动beeline连接报错: User: xxx is not allowed to impersonate anonymous (state=08S01,code=0)

Proxy user - Superusers Acting On Behalf Of Other Users

beeline执行insert命令时报错Permission denied: user=anonymous, access=EXECUTE, inode=”/tmp/hadoop-yarn”:xiao

Hive中的日志