hive深入使用

Posted by BY KiloMeter on February 2, 2019

metastore数据库备份与还原

上面的那篇blog中可以看到,mysql中的metastore数据库十分重要,因此需要定期对该数据库进行备份,备份过程就是跟我们以前在J2EE上学的数据库导入一样,在命令行输入以下命令。

mysqldump -u root -p metastore > metastore.sql

因为可以通过命令行来进行备份,所以可以使用oozie,azkaban等工具进行自动化管理。

既然有备份,那就有还原,还原的命令如下

mysql -u root -p metastore < metastore.sql

hive数据的导出

通常hive的数据是保存在hdfs上的,也可以选择备份到本地上

insert overwrite local directory "要保存的位置" row format delimited fields terminated by '\t' select * from 表名

也可以使用bash用hive 加上-e 或-f导出

bin/hive -e "select * from 表名" > 目录文件

单独备份到hdfs上

insert overwrite directory "要保存的位置" select * from 表名

hive的定期执行

假如现在有一个需求,需要你在某个特定的时间点使用hive进行数据的清洗,该如何实现呢。

上面提到,可以使用oozie,azkaban等自动化工具,但是,这些自动化工具执行的都是bash脚本,而我们执行的hive语句不是bash语句,而是在hive的客户端上执行的。这个时候可以在hive的查询语句中加入-e和-f参数。

格式如下

bin/hive -e ""  # 在这里直接写入要使用的hql语句
bin/hive -f 文件.hql # 文件中写入要执行的hql语句

有了上面两个参数,相当于在bash中使用hive,因此,我们可以把这些语句写成脚本,用自动化工具进行管理即可。

hive在执行语句时mysql和hdfs的变化

在hive执行hql语句时,比如创建数据库,在这个时候会在hdfs上创建一个/usr/hive/werehouse/目录下创建一个****.db目录,这个目录下保存了所有的表数据,(注:hive本身不存储任何数据)且会在mysql的metastore中保存hdfs中关于表的索引信息以及数据和字段的映射关系。

在新建一个abc表之后,会在前面提到的****.db目录下生成abc.txt的文件,该文件存放着表中的所有数据,hdfs新建表格后,hive能够获取到该表格所在hdfs的位置,并且hive将位置信息保存在mysql的metastore数据库中。每次hive进行查询时,会先去mysql的metastore数据库查询关于这个表所在hdfs的位置信息,hive拿到这些索引信息后,再去操作hdfs上的数据。

内部表和外部表

内部表和外部表的创建

hive默认创建的表示内部表

创建外部表

CREATE EXTERNAL TABLE

内部表和外部表的区别与联系

内部表:删除表数据的时候,连同hdfs上的数据源和mysql的元数据信息同时删除。

外部表:删除表数据的时候,只会删除mysql的元数据信息。

相同之处:在导入hdfs的数据时,之前提到,hive本身是不存储任何数据的,hive处理的数据是存放在hdfs的werehouse目录下的db文件里面,如果原来要导入的数据也是在hdfs上,hive就会把原来的数据剪切到hdfswerehouse目录下,并把文件之间的映射关系存储到mysql的metastore中,而不是对源文件进行复制。这样做的目的是,因为hdfs会对文件进行备份,如果在对数据进行转储迁移的话,会消耗很大的空间,仅把文件进行剪切移动,可以节省hdfs的空间。如果要导入的数据是在机器本地的话,实际上hive是先把文件上传至hdfs,然后执行跟前面一样的操作。

利用外部表不能删除数据源这个特性,很容易实现数据的共享,也比较安全。

hive分区表

分区表的创建

create table if not exists db_web_data.track_log(id string,currentPage string,
,resultSum string)
partitioned by (date string,hour string) -- 分区表的分区字段以逗号分隔
row format delimited fields terminated by '\t';

插入数据时还要输入分区

load data local inpath '/usr/local/test/hqldata/2015082818' into table track_log partition(date='20150828',hour='18');

查询分区表的数据

select * from track_log where date = '20150828' and hour = '18';
select * from track_log where date = '20150828';

hiveserver2

什么是hiveserver2

官方翻译:HiveServer2(HS2)是一种能使客户端执行Hive查询的服务。 HiveServer2是HiveServer1的改进版,HiveServer1已经被废弃。HiveServer2可以支持多客户端并发和身份认证。旨在为开放API客户端(如JDBC和ODBC)提供更好的支持。

简单来说就是为hive提供了其他方式使用hive,如JDBC。

hiveserver2 是什么

hiveserver的配置

修改hive-site.xml配置文件

<property>
  <name>hive.server2.long.polling.timeout</name>
  <value>5000</value>
  <description>Time in milliseconds that HiveServer2 will wait, before responding to asynchronous calls that use long polling</description>
</property>

<property>
  <name>hive.server2.thrift.bind.host</name>
  <value>niubike1</value>
  <description>Bind host on which to run the HiveServer2 Thrift interface.
  Can be overridden by setting $HIVE_SERVER2_THRIFT_BIND_HOST</description>
</property>
<!--默认使用的是10000端口,配置后需要查看下该端口是否被占用  netstat -antp| grep 10000-->
<property>
  <name>hive.server2.thrift.port</name>
  <value>10000</value>
  <description>Port number of HiveServer2 Thrift interface.
  Can be overridden by setting $HIVE_SERVER2_THRIFT_PORT</description>
</property>

hiveserver2的启动和使用

hiveserver2的启动

bin/hive --service hiveserver2

上述启动后,开启一个新的窗口去连接该服务。

bin/beeline
# 进入beeline后,使用下面的命令进行连接hive
!connect jdbc:hive2://niubike1:10000
# 在连接使用的时候会提示我们要输入用户名和密码,在这里只需要直接回车即可。

但是上述配置后只能进行普通的查询操作,对于聚合等这些需要用到MapReduce的操作无法执行,因为没有权限开启MapReduce任务。

<property>
  <name>hive.server2.enable.doAs</name>
  <!--将值改为true-->
  <value>false</value>
  <description>
   Setting this property to true will have HiveServer2 execute
    Hive operations as the user making the calls to it.
  </description>
</property>

UDF用户自定义函数

可以自己定义在hive中使用的函数。

第一步:引入jar包

<dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>2.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>0.13.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-exec</artifactId>
            <version>0.13.1</version>
        </dependency>
    </dependencies>

第二步:创建类并继承UDF,实现自定义方法并且在主函数中进行调用,如下。

public class ToLowCase extends UDF{
    public Text evaluate(Text str){
        if(str==null||str.toString().length()==0)
            return null;
        return new Text(str.toString().toLowerCase());
    }

    public static void main(String[] args) {
        System.out.println(new ToLowCase().evaluate(new Text(args[0])));
    }
}

第三步:将程序打成jar包并扔到虚拟机上。

第四步:在hive中添加该jar包并且将该函数加入到hive中

add jar /usr/local/test/jar/hiveUDF-1.0-SNAPSHOT.jar;
create temporary function zlowercase as 'com.km.hive.ToLowCase';

添加后可以使用show functions查看是否添加该方法到hive中。然后就能使用该函数了,上面的函数是把所有的输入字符串转全部换成小写。

select zlowercase(ename) from emp;

hive的其他零碎知识点

问:如何查看hive的历史输入命令

答:在刚登录系统的用户路径下(可以使用 cd +回车,注意不是根目录),使用 cat .hivehistory查看

问:如何设置hive的临时生效值(就是在hive的客户端中,不想要退出去修改配置文件信息再启动hive)

答:在hive的客户端中,直接使用set 属性名=属性值即可。例如:set hive.cli.print.header=false;

(注:由于是临时生效值,因此退出这次客户端后,再次重启客户端,本次设置将会失效)