Hive
一、操作Hive的两种方式
1、通过Beenline
操作Hive可以直接通过hive命令进入Hive client直接连接HDFS、Yarn进行数据分析以及处理,但是这种方式既不安全也不规范。因此,才有了Beeline,Beeline需要提前与ThriftServer连接,然后进行安全验证,间接的与HDFS、Yarn建立连接,实现解耦。
由于Beeline默认链接hiveserver2的时候也不需要用户名、密码,因此默认方式也是不安全的,但是我们可以设置hiveserver2用户名、密码。
在hive-site.xml配置文件中设置用户名、密码:
<property>
<name>hive.server2.authentication</name>
<value>CUSTOM</value>
</property>
<property>
<name>hive.jdbc_passwd.auth.zhangsan</name>
<value>123456789</value>
</property>
<property>
<name>hive.server2.custom.authentication.class</name>
<value>com.hpe.hive.authoriz.UserPasswdAuth</value>
</property>
用户自定义代码进行登录验证:
package com.hpe.hive.authoriz;
import javax.security.sasl.AuthenticationException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hive.conf.HiveConf;
import org.apache.hive.service.auth.PasswdAuthenticationProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class UserPasswdAuth implements PasswdAuthenticationProvider {
Logger logger = LoggerFactory.getLogger(UserPasswdAuth.class);
private static final String USER_PASSWD_AUTH_PREFIX = "hive.jdbc_passwd.auth.%s";
private Configuration conf = null;
@Override
public void Authenticate(String userName, String passwd) throws AuthenticationException {
logger.info("user: " + userName + " try login.");
String passwdConf = getConf().get(String.format(USER_PASSWD_AUTH_PREFIX, userName));
if (passwdConf == null) {
String message = "沒有发现密码 " + userName;
logger.info(message);
throw new AuthenticationException(message);
}
if (!passwd.equals(passwdConf)) {
String message = "用户名密码不匹配" + userName;
throw new AuthenticationException(message);
}
}
public Configuration getConf() {
if (conf == null) {
this.conf = new Configuration(new HiveConf());
}
return conf;
}
public void setConf(Configuration conf) {
this.conf = conf;
}
}
链接Beenline的两种方式:
第一种链接方式:
./beeline -u jdbc:hive2://node01:10000/test -n zhangsan -p123456789
第二种链接方式:
./beeline
!connect jdbc:hive2://node01:10000/test
输入用户名
输入密码
2、通过JDBC
JDBC链接Hive与Beenline链接Hive一样,也是链接hiveserver2服务,链接成功才能操作Hive,为了安全JDBC链接Hive的时候也需要用户名和密码。
package com.hpe.hive.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class ConnectHive {
public static String driverName = "org.apache.hive.jdbc.HiveDriver";
public static void main(String[] args) {
try {
Class.forName(driverName);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String url = "jdbc:hive2://node01:10000";
String userName = "zhangsan";
String passwd = "123456789";
Connection conn = null;
try {
conn = DriverManager.getConnection(url, userName, passwd);
Statement statement = conn.createStatement();
String sql = "select * from test.logtbl limit 10";
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()) {
System.out.println(resultSet.getString(1) + "-" + resultSet.getString(2));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
二、Hive的优化
1、Hive优化的思想:
把Hive SQL当作MapReduce来进行优化。但是查询本表字段、对本表字段进行过滤的SQL语句不会转化成MapReduce来执行。
2、优化的方式
Hive运行方式:
- 本地模式
- 集群模式
(1)开启本地模式
set hive.exec.mode.local.auto=true;
但是得满足以下条件才能使用本地模式:
- 输入数据大小必须小于参数(默认128M)
- map数必须小于参数(默认4)
- reduce数必须等于0/1
(2)开启并行计算
set hive.exec.parallel=true;
(3)严格模式
- 通过设置
set hive.mapred.mode=strict;
开启严格模式 - 查询限制
- 对于分区表,必须添加where对于分区字段的条件过滤。
- order by语句必须包含limit限制。
- 限制笛卡尔积的查询。
(4)Hive排序
- Order By:对于查询结果做全排序,只允许有一个reduce处理 (当数据量较大时,应慎用。严格模式下,必须结合limit来使用)
- Sort By:对于单个reduce的数据进行排序。
- Distribute By:经常和Sort By结合使用达到分区排序的效果。
- Cluster By:相当于 Sort By + Distribute By,但是Cluster By不能通过ASC、DESC的方式指定排序规则。但是可通过
distribute by column sort by column asc|desc
来进行指定排序。
(5)Hive Join
- Join计算时,将小表放在左边。
- Map Join:在Map端完成Join。
两种实现方式:
- SQl方式:在SQl语句中添加Map join标记。
- 开启自动的
Map joinset hive.auto.convert.join = true;
该参数为true时,Hive自动对左边的表统计数据量,如果是小表就加入内存,即对小表使用Map join
相关配置参数:
- hive.mapjoin.smalltable.filesize;(大表小表判断的阈值,如果表的大小小于该值则会被加载到内存中运行)
- hive.ignore.mapjoin.hint;(默认值:true;忽略mapjoin hint 即mapjoin标记)
- hive.auto.convert.join.noconditionaltask;
(默认值:true;将普通的join转化为普通的mapjoin时,是否将多个mapjoin转化为一个mapjoin) - hive.auto.convert.join.noconditionaltask.size;
(将多个mapjoin转化为一个mapjoin时,其表的最大值)
(6)Map-Side聚合
设置combinerset hive.map.aggr=true;
开启在Map端额聚合。
相关的配置参数:
- hive.groupby.mapaggr.checkinterval: 默认100000;map端group
by执行聚合后产生的最大记录数(默认:100000) - hive.map.aggr.hash.min.reduction:默认0.5 ;进行聚合的最小比例
- hive.map.aggr.hash.percentmemory: 默认0.5 ;map端聚合使用的内存占总内存的比例
- **hive.map.aggr.hash.force.flush.memory.threshold:默认0.9 **
- map端做聚合操作是hash表的最大可用内容,大于该值则会触发flush;map端做聚合操作是hash表的最大可用内容,大于该值则会触发flush
- hive.groupby.skewindata;是否对GroupBy产生的数据倾斜做优化,默认为false
(7)控制Hive中Map以及Reduce的数量
Map数量相关的参数:
- mapred.max.split.size 一个split的最大值,即每个map处理文件的最大值
- mapred.min.split.size.per.node 一个节点上split的最小值
- mapred.min.split.size.per.rack 一个机架上split的最小值
Reduce数量相关的参数
- mapred.reduce.tasks 强制指定reduce任务的数量
- hive.exec.reducers.bytes.per.reducer 默认 256M
- 每个reduce任务处理的数据量
- hive.exec.reducers.max 默认1009每个任务最大的reduce数
(8)Hive - JVM重用
适用场景:
1、小文件个数过多
2、task个数过多
通过set mapred.job.reuse.jvm.num.tasks=n;
来设置(n为task插槽个数)
缺点:
设置开启之后,task插槽会一直占用资源,不论是否有task运行,直到所有的task即整个job全部执行完成时,才会释放所有的task插槽资源。