Hive全方面攻略

概述

Apache Hive™数据仓库软件有助于使用SQL读取,编写和管理驻留在分布式存储中的大型数据集。可以将结构投影到已存储的数据中。提供了命令行工具和JDBC驱动程序以将用户连接到Hive。它是一个构建在Hadoop上的数据仓库框架。

简单点来说,hive是为了替代hadoop的mapreduce。

从数据计算的角度来说:

mapreduce分布式计算难度大,而hive是用sql语句来进行数据分析的,简化开发,减少学习成本(sql简单学习)。mysql不可以处理大数据量,而hive可以处理。hive可以替代mapreduce,但是一些复杂的mapreduce,hive还是不能替代。

Hive优缺点

优点:

  1. 操作接口采用了sql,可以简化开发,减少学习成本。
  2. 避免手写MapReduce程序。
  3. hive执行延迟高,适用场景大于用于实时性要求不高的场景,如处理历史数据。
  4. 处理大数据。
  5. 依赖hdfs文件系统作存储,所以它也属于分布式。
  6. 支持自定义函数。(把功能封装成函数,用sql执行)

缺点:

  1. hive的sql表达能力有限(简称HQL),即并不是所有大数据应用场景都可以使用,还需要结合mapreduce。
  2. hive效率低,因为sql需要解析成mqpreduce程序再执行,影响效率
  3. 调优难,因为粒度粗,不好优化。

Hive架构

Hive把SQL查询转换成一系列在Hadoop集群上运行的Job。Hive把存储在HDFS上的数据转换成表的结构,其中元数据(meta)则存储在metastore数据库中。

在这里插入图片描述

  1. client代表hive的一系列操作接口,如hive shell、jdbc/odbc、web ui。当这些接口发送一个查找数据的请求时,首先,会通过meta来查看数据属于哪个表。
  2. meta是hive表的元数据信息,默认以表形式存储在derby数据库中,表名为metastore,但是由于derby不支持多客户端连接,所以推荐使用mysql来替代。
  3. 从meta查看到需要的元数据后,首先会进入SQL Parser解析器,解析器的作用是把sql语句解析成相对应的MapReduce。
  4. 解析器之后是Physical编译器,程序需要编译过后才能执行。
  5. 程序编译完毕会进入Query优化器,Query优化器的作用是对hive进行优化,并不是所有的sql都需要运行一个mr计算,如select all语句查询表中所有内容的,就不需要计算。
  6. 最后进入Execution执行器,这里是真正执行MR程序的地方。

安装部署

  1. 下载安装包:
    http://hive.apache.org/downloads.html
  2. 上传安装包到服务器
  3. 解压
    tar -zxvf .tar
  4. 修改配置 conf/hive-env.sh.template重命名为hive-env.sh
    vi hive-env.sh
    #指定hadoo的目录
    HADOOP_HOME=/home/even/hd/hadoop-2.8.4
    #配置hive的配置文件
    export HIVE_CONF_DIR=/home/even/hd/hive/conf
  5. 启动hive前启动hadoop集群
    start-dfs.sh
    start-yarn.sh
    或者
    start-all.sh
  6. 在hdfs上创建文件夹
    hdfs dfs -mkdir /tmp
    hdfs dfs -mkdir -p /user/hive/warehouse/
  7. 启动hive
    bin/hive

Hive测试

  1. 查看数据库
    show databases;

  2. 使用数据库
    use default;

  3. 查看表
    show tables;

  4. 创建表
    create table user(id int, name string);

  5. 插入数据
    insert into user values(1,“even”);

  6. 查询
    select * from user;

  7. 删除表
    drop table user;

  8. 退出终端
    quit;

操作数据

  1. 准备数据
    vi user.txt
    1 even
    2 zhangsan
    3 lala
    4 elina
    5 haha
  2. 创建数据库
    create database hive_db;
  3. 使用数据库
    use hive_db;
  4. 创建hive表(row format delimited fields terminated by ‘\t’:表明数据文件的每一行是由制表符分隔的文本)
    create table usertable(id int,name string) row format delimited fields terminated by ‘\t’;
  5. 加载数据(加载本地文件数据到hive表中,会把文件复制生成的表的hdfs目录下,如果没有local,则是把hdfs对应目录的文件移动到表的hdfs目录下)
    load data local inpath ‘/home/even/hd/user.txt’ into table usertable;
    在这里插入图片描述

Hive配置

配置文件 conf/hive-site.xml

  1. 启动指定配置文件(配置HIVE_CONF_DIR环境变量是全局配置):
    hive --config 配置文件所有目录的绝对路径
  2. fs.defaultFS
    hdfs文件系统,默认本地hdfs文件系统
  3. yarn.resourcemanager.address
    yarn资源管理器
    例:hive -hiveconf fs.defaultFS=hdfs://localhost -hiveconf mapreduce.framework.name=yarn -hiveconf yarn.resourcemanager.address=localhost:8032
    (注意:如果要让多个hive用户共享一个hadoop集群,需要使hive所用的目录树对所有用户可写)
  4. hive shell中设置配置,例:设置表的定义使用“分桶”
    hive>SET hive.enforce.bucketing=true; #设置属性
    hive>SET hive.enforce.bucketing #查看属性
    hive>SET #列出所有非默认值
    hive>SET -v #列出所有属性值,包括默认值

配置信息优先级:
1,Hive SET命令
2, -hiveconf选项
3,hive-site.xml 和Hadoop站点文件(core-site.xml,hdfs-site.xml,mapreduce-site.xml,yarn-site.xml)
4,hive默认值和hadoop默认文件(core-site.xml,hdfs-site.xml,mapreduce-site.xml,yarn-site.xml)

Hadoop执行引擎

Hive的默认是以MapReduce作为执行引擎,另还支持Apache Tez(http://tez.apache.org/)和Spark引擎。Tez和Spark是通用有向无环图(DAG)引擎,相比MapReduce更加灵活且性能优越。

在使用MapReduce引擎时,中间job的输出会被materialize存储到hdfs上,而Tez和Spark则可以根据Hive规划器的请求,把中间结果写到本地的磁盘或者是内存k缓存,以提高性能,避免复制的开销。

可通过设置hive-site.xml的hive.execution.engine属性来选择引擎。

Hadoop日志

默认在本地文件系统的${java.io.tmpdir}/${user.name}/hive.log,一般情况下,${java.io.tmpdir}就是/tmp目录,可以通过hive.log.dir属性设置。

Hive服务

Hive命令提供了一系列的服务,其中,直接输入hive启动shell环境只是其中的一种,可以通过hive --service help来查看可用的服务列表。然后使用hive --service serviceName来启动服务:

  1. Cli
    hive命令行默认的服务,相当于直接输入hive
  2. hiveserver2
    让hive以提供Thrift服务的服务器形式运行,可以使用不同语言编写的客户端进行访问,如Thrift,JDBC和ODBC连接器的客户端都可以与hive服务器通信,可以通过hive.server2.thrift.port指定服务器监听的端口,类似mysql的3306
  3. jar
    和hadoop jar作用一样,让Java应用程序运行在hadoop集群中
  4. metastore
    默认情况下,metastore和hive服务运行在同一个线程,使用此服务,可以让metastore作为一个单独的进程执行。可通过设置METASTORE_PORT环境变量指定服务器监听的端口号(默认为9083)

Hive客户端

如果hive以服务器的形式运行,则可以通过应用程序来连接服务器。

  • Thrift客户端:hiveserver2是以提供thrift服务的服务器形式运行的,因此,任何运行Thrift的编程语言的客户端都可以与之交互。
  • JDBC驱动:Hive提供了JDBC的驱动,定义在org.apache.hadoop.hive.jdbc.HiveDriver类中,可以以jdbc:hive2://host:port/dbname形式配置JDBC URI,Java应用程序连接hive服务器,实际上驱动是使用java的Thrift绑定来调用Hive Thrift客户端实现的接口。
  • ODBC驱动:可允许支持ODBC协议的应用程序连接Hive服务器。

在这里插入图片描述

Metastore

metastore是Hive元数据存储的地方,主要包括两部分:服务和后台数据的存储。默认情况下,metastore服务和hive服务运行在同一个JVM中,以一个内嵌的以本地磁盘为存储的Derby数据库来实例,即内嵌metastore配置
每次只有一个Derby数据库可以访问磁盘中的数据库文件,所以,一个只能为一个metastore打开一个Hive会话,即不支持多会话连接。
如果需要支持多会话连接,需要一个独立的数据库,使用独立的数据库,metastore服务仍然和hive服务运行在同一个进程中,但是,连接的数据库却已是另一个进程运行的,而不是本进程内嵌的,此种配置为本地metastore配置

metastore的相关配置:

属性名称 类型 默认值 描述
hive.metastore.warehouse.dir URI /user/hive/warehouse 管理表就存储在这里
hive.metastore.uris 逗号分隔的URI 连接由URI列表指定的远程metastore服务器。以轮询方式连接。默认使用当前的metastore
javax.jdo.option.ConnectionURL URI jdbc:derby:;Name=metastored b;create=true metastore数据库的JDBC URL
javax.jdo.option.ConnectionDriverName 字符串 org.apache.derby.jdbc.EmbeddedDriver JDBC驱动器的类名
javax.jdo.option.ConnectionUserName 字符串 APP JDBC用户名
javax.jdo.option.ConnectionPassword 字符串 mine JDBC密码

以上属性使用javax.jdo前缀,原因是因为metastore的实现针对持久化java对象使用了Java Data Object API,DataNucles实现。另还需要在指定驱动类后,需要把驱动类放入hive的lib目录。

远程metastore配置,即把一个或多个metastore服务器和hive服务运行在不同的进程内,远程metastore配置可以使数据库置于防火墙之后,客户端无需数据库凭据。

可通过设置hive.metastore.uris配置metastore服务器列表,metastore服务器URI的形式为thrift://host:port,此处端口号为上面提及到METASTORE_PORT值。

在这里插入图片描述

配置Hive默认Meta的数据库

CentOS7 安装Mysql

  1. 检查MySQL是否已安装
    yum list installed | grep mysql
  2. 卸载旧版本的Mysql
    yum -y remove 数据库名称
    在这里插入图片描述
  3. 安装Mysql依赖libaio。
    yum search libaio #检索相关信息
    yum install libaio #安装依赖包
  4. 下载MySQL Yum Repository,如果没有wget工具,就先用yum install wget安装
    wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm
  5. 添加MySQL Yum Repository
    添加Yum Repository到系统repository列表中。
    yum localinstall mysql-community-release-el7-5.noarch.rpm
  6. 检查是否添加成功
    yum repolist all | grep mysql
    在这里插入图片描述
  7. yum repolist enabled | grep mysql
    在这里插入图片描述
  8. 通过yum安装MySQL,遇到提示按y
    yum install mysql-community-server
  9. 安装成功后查看:
    在这里插入图片描述
  10. 执行whereis mysql,发现mysql在/usr/bin
    在这里插入图片描述

启动关闭mysql

  1. 启动mysql
    systemctl start mysqld
  2. 查看mysql server状态
    systemctl status mysqld
  3. 关闭mysql
    systemctl stop mysqld

防火墙设置

firewall-cmd --permanent --zone=public --add-port=3306/tcp #开放默认端口3306

firewall-cmd --reload #重启

或systemctl stop firewall #直接关闭防火墙

MYSQL设置安全信息

mysql_secure_installation

要求输入root初始密码,默认为空,然后设置新密码。后面根据提示一直y。

mysql 授权命令:
grant all privileges on . to ‘root’@’%’ identified by ‘password’ with grant option;

flush privileges; //刷新权限

Hive配置Mysql

  1. 把mysql-connector-java-5.1.39.jar包拷贝到HIVE_HOME/lib目录下
  2. 配置Metastore到mysql,在hive_home/conf目录创建一个hive-site.xml
    根据官方文档配置参数,拷贝数据到hive-site.xml文件中,特别注意,value标签的内容两边不要有空格,mysql防火墙要关闭
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
    <property>
        <name>javax.jdo.option.ConnectionURL</name>
        <value>jdbc:mysql://hd-even-01:3306/metastore?createDatabaseIfNotExist=true</value>
        <description>JDBC connect string for a JDBC metastore</description>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionDriverName</name>
        <value>com.mysql.jdbc.Driver</value>
        <description>Driver class name for a JDBC metastore</description>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionUserName</name>
        <value>root</value>
        <description>username to use against metastore database
        </description>
    </property>
    <property>
        <name>javax.jdo.option.ConnectionPassword</name>
        <value>root</value>
        <description>password to use against metastore database
        </description>
    </property>
</configuration>

Hive数据类型

Java数据类型 Hive数据类型 描述 类型
byte TINYINT 1byte 原子
short SMALINT 2byte 原子
int INT 4byte 原子
long BIGINT 8byte 原子
float FLOAT 单精度浮点数
double DOUBLE 双精度浮点数
string STRING 字符
TIMESTAMP 时间类型
BINARY 字节数组
Date DATE 日期
array ARRAY 一组有序字段,字段类型必须相同
map MAP 一组无序键-值对,键的类型必须是原子级的。同一个map的键和值类型必须相同
STRUCT 一组命名的字段。字段类型可以不同
UNION 值的数据类型可以是多个被定义的数据类型中的任意一个,该数据类型通过一个整数来标记

DDL数据定义语言

CREATE、ALTER、DROP等sql语句,用于创建或修改表结构,数据类型,表之间的关系和约束等初始化的工作。

  1. 创建数据库
=>查看数据库
show databases;
=>创建数据库
create database hive_db;
=>创建数据库标准写法
create database if not exist db_hive;
=>创建数据库指定所在hdfs路径
create database hive_db1 location '/hive_db';
  1. 修改数据库
=>查看数据库结构
desc database hive_db;
=>添加描述信息
alter database hive_db set dbproperties('datais'='even');
=>查看拓展属性
desc database extended hive_db;
  1. 查询数据库
=>显示数据库
show databases;
=>筛选查询的数据库
show database like 'hive*';
  1. 删除数据库
=>删除数据库
drop database hive_db;
=>删除数据库标准写法
drop database if exists hive_db;
  1. 创建表
=>创建表,行格式化且以fields为界限,以"\t"为分隔
>create table db_h(id int,name string)
>row format
>delimited fields
>terminated by "\t";

表类型

  1. 管理表(内部表)
    加载数据到管理表时,Hive把数据移到仓库目录
#不擅长做数据共享,因为在删除hive中管理表时,数据也会被删除
=>加载数据
load data local inpath 'home/even/hd/even.txt' into table emp;
=>查询并保存到一张新的表
create table if not exists emp2 as select * from emp where name='even';
=>查询表结构
desc formated emp;
Table Type:	MANAGED_TABLE
==>删除表,此操作会把管理表的数据包括元数据全删除了
drop table emp2
  1. 外部表
    使用external关键字,表示创建的表是外部表。此操作不会把数据移到自己的仓库目录。甚至在定义时,不会检查这一外部位置是否存在。删除外部表时,hive只会删除元数据。
#hive不认为这张表拥有这份数据,当删除该表时,数据不删除,擅长做数据共享
=>创建外部表
>create external table if not exists emptable(empno int,ename string,job string,mgr int,birthday string,sal double,comm double,deptno int)
>row format
>delimited fields
>terminated by '\t';
=>导入数据
load data local inpath '/home/even/hd/emp.txt' into table emptable;
=>查看表结构
desc formatted emptable
Table Type:	EXTERNAL_TABLE
=>删除表
drop table emptable;
再次创建相同的表,字段相同,将自动关联数据

1,针对管理表和外部表的用法,一般是把存放在hdfs的初始数据集用作外部表进行使用,然后用hive的变换功能把数据移到管理表。2,所有处理都由hive完成的,应该使用管理表,如果要用hive和其他工具共同处理同一个数据集,就用外部表。3,当同一个数据集需要关联不同的模式时,也需要使用外部表。

  1. 分区表
=>创建分区表
>create table dept_partitions(depno int,dept string,loc string)
>partitioned by(day string)
>row format
>delimited fields
>terminated by '\t';
=>加载数据
load data local inpath '/home/even/hd/dept.txt' into table dept_partitions;
注意:会报错,不能直接导入,需要指定分区
load data local inpath '/home/even/hd/dept.txt' into table dept_partitions partition(day='1112');
=>添加分区
alter table dept_partitions add partition(day='1113');
=>单分区查询
select * from dept_partitions where day='1112';
=>全查询
select * from dept_partitions;
=>查询表结构
desc formatted dept_partitions;
=>删除单个分区
alter table dept_partitions drop partition(day='1112');
  1. 分桶表
分区表分的是数据的存储路径
分桶针对数据文件
1. 创建分桶表
create table emp_buck(id int,name string)
clustered by(id) into 4 buckets
row format
delimited fields
terminated by '\t';
2. 设置属性
set hive.enforce.bucketing=true;
3. 导入数据
insert into table emp_buck select * from emp_b;
注意:分区分的是文件夹 分桶是分的文件
适用于抽样测试
  1. 修改表
=>修改表名
alter table emptable rename to new_emp_table;
=>添加列
alter table dept_partitions add columns(desc string);
=>更新列
alter table dept_partitions change columns desc descc int;
=>替换
alter table dept_partitions replace column(descc int);

Hive存储格式

Hive从两个维度来对表的存储进行管理,分别是行格式(ROW FORMAT)和文件格式(FILE FORMAT)。

ROW FORMAT:行格式指行和一行中的字段如何存储。行格式由SerDe定义,当执行INSERT或CTAS操作时,表的SerDe会把hive的数据行内部表示形式序列化成字节形式并写到输出文件中。如Select操作时,SerDe会把文件中字节形式的数据行反序列化为hive内部操作数据行。

FILE FORMAT:指一行(ROW)中字段容器的格式。最简单的格式是纯文件文件。

默认使用每行(line)存储一个数据行(row),可以通过hive.default.fileformat属性设置默认格式。默认行内分隔符使用Control-A(ASCII码为1),集合类元素默认分隔符为字符Control-B,用于分隔ARRAY或STRUCT或MAP的键-值对中的元素。默认的映射键(map key)分隔符为字符Control-C,用于分隔MAP的键和值。表中各行之间用换行符分隔。

DML数据操作语言

SELECT、UPDATE、INSERT、DELETE、LOAD语句,主要用来对数据库的数据进行操作。

 1. 向表中加载数据
load data local inpath '/home/even/hd/even.txt' into table even;
 2. 加载hdfs中数据
load data inpath '/even.txt' into table even;
提示:因为Hive数据是保存在hdfs中的,因此,此处的操作相当于剪切,把数据从hdfs的一个路径,复制到表对应的路径。
 3. 覆盖原有的数据
load data local inpath '/home/even/hd/even1.txt' overwrite into table even;
 4. 创建分区表
create table even_partitions(id int,name string) partitioned by (month string) row format delimited by fields terminated by '\t';
 5. 向分区表插入数据
insert into table even_partitions partition(month='201901') values(1,'hmb');
 6. 按照条件查询结果并存储到新表
create table if not exists even_partions1 as select * from even_partitions where name='hmb';
 7. 创建表时加载数据
>create table db_h(id int,name string)
>row format
>delimited by fields
>terminated by '\t'
>location '数据路径';
 8. 查询结果导出到本地
insert overwrite local directory '/home/even/hd/elina.txt' select * from even where name='hmb';
或
hive -e 'select * from even' > /home/even/hd/elina.txt
或
dfs -get /user/hive/warehouse/0000 /home/even/hd;

配置查询头信息

在hive-site.xml
<property>
	<name>hive.cli.print.header</name>
	<value>true></value>
</property>
<property>
	<name>hive.cli.print.current.db</name>
	<value>true></value>
</property>

基本查询

=>全表查询
select * from empt;
=>查询指定列
select empt.empno,empt.empname from empt;
=>列别名
select ename name,empno no from empt;

算数运行符

算数运算符 描述
+ 相加
- 相减
* 相乘
/ 相除
% 取余
& 按位取与
| 按位取或
^ 异或
~ 按位取反

函数


 1. 求行数count
select count(*) from empt;
 2. 求最大值max
select max(empt.sal) sal_max from empt;
 3. 求最小值
select min(empt.sal) sal_min from empt;
 4. 求总和
select sum(empt.sal) sal_sum from empt;
 5. 求平均值
select avg(empt.sal) sal_avg from empt;
 6. 前两条
select * from empt limit 2;

=>where语句

 1. 工资大于1700的员工信息
 select * from empt where empt.sal > 1700;
 
 2. 工资小于1800的员工信息
select * from empt where empt.sal < 1800;
 3. 查询工资在1500到1800区间的员工信息
 select * from empt where empt.sal between 1500 and 1800;
 
 4. 查询有奖金的员工信息
 select * from empt where empt.comm is not null;
 
 5. 查询无奖金的员工信息
select * from empt where empt.comm is null;
 6. 查询工资是1700和1900的员工信息
select * from empt where empt.sal in (1700,1900);

=>Like
使用like运算选择类似的值,选择条件可以包含字母和数字

 1. 查找员工薪水第二位为6的员工信息
select * from empt where empt.sal like '_6%';
_代表一个字符
%代表0个或多个字符
 2. 查找员工薪水中包含7的员工信息
select * from empt where empt.sal like '%7%';
=》rlike
select * from empt where empt.sal rlike '[7]';

=>分组
1. Group By语句
计算empt表每个部门的平均工资
select avg(empt.sal) avg_sal,deptno from empt group by deptno;select
avg(empt.sal) avg_sal,deptno from empt group by deptno;
2. 计算empt每个部门中最高的薪水
select max(empt.sal) max_sal,deptno from empt group by deptno;
3. 求部门平均薪水大于1700的部门
select deptno,avg(sal) avg_sal from empt group by deptno having avg_sal>1
700;
注意:having只用于group by分组统计语句

=>Join操作
1. 等值join
根据员工表和部门表中部门编号相等,查询员工编号、员工名、部门名称
select e.empno,e.ename,d.dept from empt e join dept d on e.deptno=d.deptn
o;
2. 左外连接 left join
null
select e.empno,e.ename,d.dept from empt e left join dept d on e.deptno=d.
deptno;
3. 右外连接 right join
select e.empno,e.ename,d.dept from dept d right join empt e on e.deptno=
d.deptno;
4. 多表连接查询
查询员工名字、部门名称、员工地址
select e.ename,d.dept,l.loc_name from empt e join dept d on e.deptno=d.de
ptno join location l on d.loc = l.loc_no;
5. 笛卡尔积
为了避免笛卡尔积采用设置为严格模式
set hive.mapred.mode;
set hive.mapred.mode=strict;

=>排序
1. 全局排序 order by
查询员工信息按照工资升序排列
select * from empt order by sal asc;默认
select * from empt order by sal desc;降序
2. 查询员工号与员工薪水按照员工二倍工资排序
select empt.empno,empt.sal*2 two2sal from empt order by two2sal;
3. 分区排序
select * from empt distribute by deptno sort by empno desc;

自定义函数

自定义函数有三种UDF,普通UDF,用户定义聚集函数(user-defined aggregate function)UDAF及用户定义表生成函数(user-defined table-generating function)UDTF。

  • UDF作用于单个数据行,且产生一个数据行作为输出。
  • UDAF接受多个输入数据行,且产生一个输出数据行。像COUNT和MAX。
  • UDTF操作作用于单个数据行,且产生多个数据行(即一个表)作为输出
    其中UDTF用处较少。
  1. UDF(user-defined function),用户定义函数。必须使用Java语言编写。
    编写UDF需要满足两个条件:
    (1)必须是org.apache.hadoop.hive.ql.exec.UDF的子类
    (2)一个UDF必须至少实现evaluate()方法
    其中evalutate()方法可以有多个,Hive会检查UDF,看能否找到和函数调用相匹配的evaluate方法。
package com.even.hive;

import org.apache.hadoop.hive.ql.exec.UDF;

/**
 * @author even
 * @date 2019年1月11日 下午8:29:00
 * @version 1.0
 */
public class Lower extends UDF{
	//大写转换为小写
	public String evaluate(final String s) {
		if(s == null) {
			return null;
		}
		return s.toString().toLowerCase();
	}
}
#把该类打包成jar文件,然后在metastore中注册这个函数并使用CREATE FUNCTION语句为它起名。
create function lower as 'com.even.hive.Lower' using jar '/home/even/hd/lower.jar';#如果是在集群中使用,需要把文件复制到hdfs中使用。
#使用函数,udf名大小写都可以
select lower(name) from dept;
#删除函数
drop function lower;
#创建一个只在会话期间可以使用的函数,创建一个.hiverc文件以包含定义这些udf的命令
add jar /jar;
create temporary function lower as 'com.even.hive.Lower';
#运行hive时自动添加udf库
hive --auxpath /jar路径
或
设置环境变量HIVE_AUX_JARS_PATH,附加路径可以是逗号分隔的jar文件路径,也可以是包含jar文件的目录。
  1. UDAF
    编写UDAF必须是org.apache.hadoop.hive.ql.exec.UDAF的子类,且内部包含至少一个静态内部类,该静态内部类实现了org.apache.hadoop.hive.ql.UDAFEvaluator。
    编写UDAF需要实现5个方法:
    (1)init()方法,负责初始化计算函数并重设它的内部状态,相当于构造函数
    (2)iterate()方法,每次对一个新值进行聚集计算时都会调用iterate()方法。
    (3)terminatePartial()方法,Hive需要部分聚集结果时会调用terminatePartial()方法,相当于Map的combine。
    (4)merge()方法,决定要合并一部分聚集值和另一部分聚集值时会调用。相当于Reduce的合并。
    (5)terminate()方法,最终聚集结果输出,相当于reduce的输出。
package com.even.hive;

import org.apache.hadoop.hive.ql.exec.UDAF;
import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
import org.apache.hadoop.io.IntWritable;

/**
 * Project Name: Web_App
 * Des:求最大值
 * Created by Even on 2019/1/11
 */
public class Maximum extends UDAF {
    public static class MaximumIntUDAFEvaluator implements UDAFEvaluator {

        private IntWritable result;

        @Override
        public void init() {
            result = null;
        }

        public boolean iterate(IntWritable value) {
            if (value == null)
                return true;
            if (result == null) {
                result = new IntWritable(value.get());
            } else
                result.set(Math.max(result.get(), value.get()));
            return true;
        }

        public IntWritable terminatePartial() {
            return result;
        }

        private boolean merge(IntWritable value) {
            return iterate(value);
        }

        public IntWritable terminate() {
            return result;
        }

    }
}

在这里插入图片描述

Hive优化

压缩

  1. 开启Map阶段输出压缩
#开启输出压缩功能
set hive.exec.compress.intermediate=true;
#开启map输出压缩功能
set mapreduce.map.output.compress=true;
#设置压缩方式(压缩方式在前面《MapReduce数据压缩》文章时提及到)
set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
  1. 开启reduce输出端压缩
#开启最终输出压缩功能
set hive.exec.compress.output=true;
#开启最终数据压缩功能
set mapreduce.output.fileoutputformat.compress=true;
#设置压缩方式
set mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
#设置块压缩
set mapreduce.output.fileoutputformat.compress.type=BLOCK;
  1. 存储
#Hive存储格式:TextFile/SequenceFile/orc/Parquet
orc:Index Data/row Data/stripe Footer
压缩比:
orc>parput>textfile
查询速度:
orc>textfile
  1. Group by优化
    问题,对于一个mr程序,map阶段把相同key的数据分发给一个reduce,其中一个key的量很大。

解决方案:
在map端进行聚合(combiner)
set hive.map.aggr=true;
设置负载均衡:
set hive.groupby.skwindata=true;

猜你喜欢

转载自blog.csdn.net/weixin_37581297/article/details/86105670