通过上一小节对Hive-Cli的一些操作,可以掌握基本的Hive的语法了,本小节需要讲解一下Beeline客户端的一些操作,其实Beeline的语法和Hive客户端的基本一致,但是Hive自身的客户端只能自己用,别人连不上去,要想多个用户访问,必须使用HiveServer2。话不多说,直接进入Beeline-Cli输入一些语句来看一下结果,

$beeline>
$beeline>!help //查看帮助
$beeline>!close //关闭当前连接
$beeline>!connect jdbc:hiveserver2://localhost:10000/myhive
$beeline>!tables; //显式表
$beeline>show tables; //展示表
$beeline>!sh clear ; //执行shell脚本命令
$beeline>!quit; //退出beeline终端
$beeline>select count(*) from t1 ; //查询表t1的行数
$beeline>select max(*) from t1 ; //查询表t1的最大值
$beeline>select min(*) from t1 ; //查询表t1的最小值
$beeline>select sum(*) from t1 ; //查询表t1所有value值的和
$beeline>select avg(*) from t1 ; //查询表t1的平均值

limit的使用,Hive没有像MySql那样的limit start,end那样的写法实现分页,所以需要使用别的方式来实现分页。Hive使用limit的前一个参数表示的是去掉前几个数值,从下一个数值开始计数,第二个参数表示的是查询数值的个数。用limit分页明显减少shuffle的量,因为如果不用limit的话,所有的Map数据都到Reduce端上去了。

Hive中的order by跟传统的hql语言中的order by作用是一样的,会对查询的结果做一次全局排序,所以说,只有Hive的hql中制定了order by所有的数据都会到同一个reducer进行处理(不管有多少Map,也不管文件有多少的block只会启动一个reducer)。但是对于大量数据这将会消耗很长的时间去执行。

这里跟传统的sql还有一点区别:如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不能出结果,那么在这样的严格模式下,必须指定输出的条数。关于limit有几个常用的应用场景:(1)随着起始记录的增加,时间也随着增大,说明分页语句limit跟起始页码是有很大关系的。(2)严格模式可以防止用户执行那些可能意想不到的不好的影响的查询。增加limit语句可以防止Reducer额外执行很长一段时间。

Hive中指定了sort by(在reduce端进行部分排序),那么在每个reducer端都会做排序,也就是说保证了局部有序(每个reducer出来的数据是有序的,但是不能保证所有的数据是有序的,除非只有一个reducer),好处是:执行了局部排序之后可以为接下去的全局排序提高不少的效率(其实就是做一次归并排序就可以做到全局排序了)。关于limit和order by/sort by的具体操作代码如下, 

$beeline>select * from t1 order by id limit 5,5 ;
//嵌套的使用
$beeline>select * from (select id,name from t1) a ;
//case when等价于if / switch case
$beeline>select id , case when id < 3 then 'small'
case when id = 3 then 'three'
else 'big'
end as de from t1 ;

由于Beeline和Hive一样,都是用来操作Hive表,因此内部使用的框架是MapReduce,接下来首先详细讲一下Map端的连接以及操作,

首先需要禁用cbo,启用hint[1]。有时面对大量的数据和频繁DML操作的表,Hive自己在执行hql的时候可能也会发生错误,走错执行路径,你可能有时会发现一条很简单的hql语句执行了半天还没出来。这时候你就需要通过查看hql的执行轨迹是否符合正确的最好的那一条。不对的话就需要我们人为的干扰hql的执行,这时候就需要hint。接下来是关于Map的连接操作。

$beeline>set hive.cbo.enable=false; //过时了
$beeline>set hive.auto.convert.join=true; //默认开启了
$beeline>set hive.mapjoin.smalltable.filesize=25000000; //设置map端连接的文件大小
select /*+ mapjoin(a) */ a.*,b.* from customers a left outer join orders b on a.id = b.cid ;(对a进行map端连接)
$beeline> set hive.auto.convert.join.noconditionaltask=true; //不需要在select中使用/*+ streamtable(customers) */暗示
关于Map的连接操作,还可以对Map bucket端进行连接,
SET hive.auto.convert.join=true; --default false 
SET hive.optimize.bucketmapjoin=true; --default false

以上是关于Map和Map bucket的连接操作,除了这个以外,Map还有一个严格模式:order by时,是否必须使用limit语句指定数量。(由于order by是对所有的数据进行排序,所以考虑到对Hive的性能,因此严格模式中必须使用limit语句对查询数据进行条数的限制。)

$beeline>set hive.mapred.mode=strict //不推荐使用,推荐下方的三个属性
$beeline>hive.strict.checks.large.query=false //大型查询检查:无limit order by,
//Orderby without limit.
//No partition being picked up for a query against partitioned table.
//Note that these checks currently do not consider data size, only the query pattern.
$beeline>set hive.strict.checks.type.safety //默认true
$beeline>set hive.strict.checks.cartesian.product //默认true
$beeline>set hive.strict.checks.large.query=false //默认false

设置了严格模式之后,接下来就是了解Map的操作,关于Map操作,就是处理Map格式的数据,然后将这些数据存储成文件名为map1.dat的文件,具体的数据如下所示,

1 phisic:80,huaxue:78,shuxue:99
2 music:80,history:78
3 tiyu:80,song:78

数据准备之后,就是将该文件内容加载到表map1中,然后使用select语句查询数据是否成功插入,具体操作代码以及运行结果如下,

beeline hive 是什么 hive beeline使用方法_beeline hive 是什么

 

熟悉了Map端的操作之后,来看看Reduce端的操作,Reduce首先可以设置它的个数。Reduce个数的设定极大影响任务执行效率,不指定Reduce个数的情况下,Hive会猜测确定一个Reduce个数,基于以下三个设定:

set hive.exec.reducers.bytes.per.reducer=<number> //每个reduce处理的字节数,默认256000000
set hive.exec.reducers.max=<number> //reduce个数的最大值,默认1009
set mapreduce.job.reduces=<number> //reduce个数,默认1

通过以上的一些命令行操作,我们已经可以简单的操作Hive了,但是操作Hive不光可以使用Hive客户端,也可以使用java语言来操作Hive,运用java就需要使用java中的jdbc来操作Hive表,首先导入一些java sql的包,然后创建App的类以及main函数,再使用getConnection来连接Hive,最后在execute方法中直接输入需要操作的语句即可。具体代码如下,

package com.lvqianqian.myhive210; 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
/**
* jdbc操纵hive表
*/
public class App {
public static void main(String[] args) throws Exception {
Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection conn = DriverManager.getConnection("jdbc:hive2:// hadoop0:10000/myhive");
Statement st = conn.createStatement();
st.execute("drop table user2");
st.close();
System.out.println("ok");
}
@Test
public void testFind() throws Exception{
Class.forName("org.apache.hive.jdbc.HiveDriver");
Connection conn = DriverManager.getConnection("jdbc:hive2:// hadoop0:10000/myhive");
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery("select * from t1");
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age");
String prv = rs.getString("province");
String city= rs.getString("city");
System.out.println(id + "," + name + "," + age + "," + prv + "," + city) ;
}
st.close();
}
}