Hive不支持传统数据库中insert插入操作,可通过load语句和sqoop进行数据的导入。
数据的导入
使用load语句执行数据的导入
使用load语句
-语法:load data [local] inpath ‘filepath’ [overwrite] into table tablename [partition (partcol1=val1, partcol2=val2,“`)]
例如:
–将student01.txt导入t2:
Load data local inpath ‘/root/data/student01.txt’ into table t2;
local 是指在操作系统目录, 如果是在htfs中就不用local;
上面的这种方式一次只能导入一个文件,下面可实现多文件导入。
例如:
–将/root/data下的所有数据文件导入t3表中,并且覆盖原来的数据:
load data local inpath ‘/root/data/’ overwrite into table t3;
目录只要写到相关目录即可,不必具体指定到某个文件。
–将HDFS中/input/student01.txt导入到t3,此时不需要加local关键字:
load data inpath ‘/input/student01.txt’ overwrite into table t3;
–将data1.txt导入partition_table
load data local inpath ‘/root/data/data1.txt’ into table partition_table partition (gender=’M’);
使用sqoop进行数据的导入
使用sqoop help命令可以对sqoop查看命令帮助
Sqoop是apache下的一个框架,专门做数据的导入和导出。
下载地址:http://www.apache.org/dyn/closer.lua/sqoop/
Sqoop要先安装:下载,tar包安装,再设置两个环境变量即可。
Linux解压tar包的命令 :tar –zxvf 包名
#export HADOOP_COMMON_HOME-~hadoop的安装目录
#export HADOOP_MAPRED_HOME-~hadoop的安装目录
在:sqoop目录的bin目录下有个sqoop,通过这个执行操作
① 使用sqoop导入oracle数据到HDFS中,sqoop语句中的‘–’表示变量
注意:需要把oracle的驱动包上传到sqoop的lib目录下
./sqoop import –connect jdbc:oracle:thin:@192.168.56.101:1521:orcl –username scott –password tiger –table emp –columns ‘empno,ename,job,sal’ -m 1 –target-dir ‘/sqoop/emp’
注释:-m表示mapreduce的进程数,如次数进程数是一个
--connect:指定jdbc连接的URL地址,用户名,密码
--table:指明导入的表
--columns:指明导入表的列
②使用sqoop导入oracle数据到hive中
./sqoop import –hive-import –connect jdbc:oracle:thin:@192.168.56.101:1521:orcl –username scott –password tiger –table emp –m 1 –columns ‘empno,ename,job,sal’
③使用sqoop导入oracle数据到hive中,并且指定表名
./sqoop import –hive-import –connect jdbc:oracle:thin:@192.168.56.101:1521:o重点内容rcl –username scott –password tiger –table emp –m 1 –columns ‘empno,ename,job,sal’ –hive-table emp1
④ 使用sqoop导入oracle数据到hive中,并使用where条件
./sqoop import –hive-import –connect jdbc:oracle:thin:@192.168.56.101:1521:orcl –username scott –password tiger –table emp –m 1 –columns ‘empno,ename,job,sal’ –hive-table emp2 –where ‘DEPTNO=10’
⑤ 使用sqoop导入oracle数据到hive中,并使用查询语句
./sqoop import –hive-import –connect jdbc:oracle:thin:@192.168.56.101:1521:orcl –username scott –password tiger –m 1 –query ‘select * from emp where SAL<2000 AND $CONDITIONS’ –target-dir ‘/sqoop/emp5’ –hive-table emp5
注意:必须有AND $CONDITIONS,固定格式
⑥ 使用sqoop将hive中的数据导出到oracle中。
./sqoop export –connect jdbc:oracle:thin:@192.168.56.101:1521:orcl –username scott –password tiger -m 1 –table myemp –export-dir **
注意:需要oracle数据库中先有myemp这个表,并且格式跟*中的一样。
就是说*的数目和myemp表中列的数目一致
正真的企业级环境数据迁移如下图:
Hive的数据查询
简单查询和fetch task
select *from emp; ---并没有转成mapreduce查询,把hdfs中对应的文件直接加载
select empno,ename,sal from emp; --- 转换层mapreduce任务 不能对表进行全表扫描 需要对数据进行分析
Hive中很多查询会转换成mapreduce的作业来执行,但有少量的查询语句不用转换成MapReduce作业。如select * from student。
为什么当在hive中执行比较简单的查询语句时,有时速度比传统的oracle速度还要慢?
因为:1、跟自己机器的配置有关系;2、使用hive要操作数据仓库,当仓库中的数据比较多时,使用hive的速度会比较快。
查询表达式中可以进行一些算术操作,并且可以用hive中的内置函数nvl()将值为null的字段转换成0。
例如:
-查询员工信息:员工号,姓名,月薪,年薪。奖金,年收入
select empno,ename,sal,sal*12,comm,sal*12+nvl(comm,0) from emp;
-查询奖金为null的员工:
select * from emp where comm=null //×错误 应该是:select * from emp where comm is null
distinct:去重,并且作用后面的所有列(组合起来的重复)
简单查询的fetch task功能
- 从hive0.10.0版本开始支持
- 配置方式(3种方式):
1、set hive.fetch.task.conversion=more; (只在当前会话中有效)
2、hive –hiveconf hive.fetch.task.conversion=more; (只在当前会话中有效)
3、修改hive-site.xml文件 (永久有效)
作用:开启该功能可在查询时不生成MapReduce的作业,提高查询效率。
注意:官网上说Hive 0.10.0到0.13.1版本默认为minimal, 而Hive 0.14.0之后的版本已经中默认为more了,不需要修改fetch.task。
在查询中使用过滤
过滤即where子句
例如:
–模糊查询:查询名字以s开头的员工:
select empno,ename,sal from emp where ename like ‘s%’;
//注意:Hive中严格区分大小写的
–模糊查询:查询名字含有下划线的员工:
select empno,ename,sal from emp where ename like ‘%\_%’;
在查询中使用排序
HIVE查询中使用排序(会被转变成mapreduce作业,执行)
降序:desc
order by 后面跟:列,表达式,别名,序号
表达式:select empno,ename,sal, sal*12 from emp order by sal*12;
别名:select empno,ename,sal,sal*12 annsal from emp order by annsal;
序号:select empno,ename,sal,sal*12 annsal from emp order by 4;
**但之使用序号前要设置一个参数:set hive.groupby.orderby.position.alias=true;//默认为false
空值是如何进行排序:
列值包含空值,升序null再前,desc反之
- 升序:null在最前面
- 降序:null在最后面**
Hive的内置函数
数学函数
round:四舍五入
例如:
select round(45.926,2), round(45.926,1), round(45.926,0), round(45.926,-1), round(45.926,-2)
结果为:45.93 45.9 46.0 50.0 0.0
注意:round函数有两个参数,第一个是要被四舍五入的数值,第二个是精确位数(例如2表示精确到小数点后两位,1表示精确到小数点后一位,0表示精确到小数点(个位),-1表示精确到十位,2表示精确到百位,以此类推)
ceil:向上取整
floor:向下取整
字符函数
lower:把字符串转成小写
upper:把字符串转成大写
length:字符串长度(字符数)
例如:
length(‘Hello World’), length(‘你好’),
上面的结果为:11 2
concat:拼接字符串
substr:求字符串的子串
substr(a,b):从a中,字符为b的位开始取,取右边所有的字符
substr(a,b,c):从a中,字符为b的位开始取,取c个字符
trim:去掉字符串前后的空格
lpad:左填充
例如:
select lpad(‘abcd’,10,’’); –对abcd进行左填充,填充到10位,多出位用 填充。
结果为: ******abcd
rpad:右填充
收集函数和转换函数
收集函数:size -求map集合元素个数
例如:
select size(map(1,’Tom’,2,’Mary’));
结果为: 2
转换函数:cast
例如:
select cast(1 as bigint), cast(1 as float), cast(‘2015-04-10’ as data);
结果为: 1 1.0 2015-04-10
日期函数
to_data:取出一个字符串中日期的部分
例如:
select to_data(‘2015-04-23 11:23:11’)
结果为: 2015-04-23
year:取出一个日期中的年YYYY
month:取出一个日期中的月MM
day:取出一个日期中的日DD
weekofyear:返回一个日期在一年中是第几个星期
datadiff:两个日期相减,返回他们相差的天数
data_add:在一个日期值上加上多少天
data_sub:在一个日期值上减去多少天
条件函数
coalesce:从左到右返回第一个不为null的值
case… when… :条件表达式
-CASE a WHEN b THEN c [WHEN d THEN e]*[ELSE f] END
例如:
给员工涨工资,总裁涨1000 经理涨800 其他涨400
select ename, job, sal,
case job when ‘PRESIDENT’ then sal+1000
when ‘MANAGER’ then sal+800
else sal+400
end
聚合函数和表生成函数
聚合函数:比较简单
Count
sum
min
avg
表生成函数
explode:把一个map集合或者数组中的每个元素单独生成一个行。
Hive的表连接
HIVE表连接(转换成mapreduce作业,提交到hadoop上)
等值连接和不等值连接
在进行多表查询时习惯给表取个别名
不等值连接:
例如:between … and …
外连接
通过外链接可以将对于连接条件不成立的记录任然包含在最后的结果中:
- 左外链接
- 右外链接
- 全外链接
自链接
自连接的核心:通过表的别名将同一张表视为多张表。
例如:
-查询员工的姓名和员工的老板姓名(员工的老板也是公司的员工):
select e.ename, b.ename
from emp e,emp b //把emp表看成两张表
where e.mgr=b.empno;
hive中的子查询
Hive只支持:form和where子句中的子查询
http://cwiki.apache.org/confluence/display/Hive/LanguageManual+SubQueries
书写子查询时要注意的问题:
- 语法中的括号不要忘了
- 合理的书写风格,方便阅读查询语句
- Hive中只支持where和from子句中的子查询
- 主查询和子查询可以不是同一张表
- 子查询中的空值问题
select * from emp e where e.empno not in (select mgr from emp e1); //可能出错,因为若子查询返回的结果中含有空值,则不能使用not in,没有空值则可以使用not in。所以因应改为select * from emp e where e.empno not in (select mgr from emp e1 where e1.mgr is not null);
hive的JDBC客户端操作
启动hive的远程服务
- #hive –service hiveserver
启动成功会出现:Starting Hive Thrift Server
步骤:
获取连接——》创建运行环境——》执行HQL——》处理结果——》释放资源
所需的驱动包如下:
这些包可以从hive的lib中找到,或者hadoop的lib中找到
例如:
JDBCUtils.java文件的源代码
package demo.utils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JDBCUtils {
private static String driver = "org.apache.hadoop.hive.jdbc.HiveDriver";
private static String url = "jdbc:hive://192.168.56.31:10000/default";
//注册驱动
static{
try {
Class.forName(driver);
} catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError(e);
}
}
//获取连接
public static Connection getConnection(){
try {
return DriverManager.getConnection(url);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
//释放资源
public static void release(Connection conn,Statement st,ResultSet rs){
if(rs != null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}finally{
rs = null;
}
}
if(st != null){
try {
st.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
st = null;
}
}
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally{
conn = null;
}
}
}
}
HiveJDBCDemo.java文件的源代码:
package demo.hive;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import demo.utils.JDBCUtils;
public class HiveJDBCDemo {
/**
* @param args
*/
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
String sql = "select * from emp";
try {
//获取连接
conn = JDBCUtils.getConnection();
//创建运行环境
st = conn.createStatement();
//运行HQL
rs = st.executeQuery(sql);
//处理数据
while(rs.next()){
//取出员工的姓名和薪水
String name = rs.getString(2);
double sal = rs.getDouble(6);
System.out.println(name+"\t"+sal);
}
} catch (Exception e) {
e.printStackTrace();
}finally{
JDBCUtils.release(conn, st, rs);
}
}
}
hive的Thrift客户端操作
例如
HiveThriftClient.java文件的源代码
package demo.hive;
import java.util.List;
import org.apache.hadoop.hive.service.HiveClient;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
public class HiveThriftClient {
public static void main(String[] args) throws Exception{
//创建Socket;连接
final TSocket tSocket = new TSocket("192.168.56.31", 10000);
//创建一个协议
final TProtocol tProtcal = new TBinaryProtocol(tSocket);
//创建Hive Client
final HiveClient client = new HiveClient(tProtcal);
//打开Socket
tSocket.open();
//执行HQL
client.execute("desc emp");
//处理结果
List columns = client.fetchAll();
for(String col:columns){
System.out.println(col);
}
//释放资源
tSocket.close();
}
}
hive中的自定义函数简介
Hive的自定义函数(UDF):User Defined Function
可以直接应用于select语句,对查询结果做格式化处理后,再输出内容
Hive自定义函数的是实现细节:
- 自定义UDF需要继承org.apache.hadoop.hive.ql.UDF
- 需要实现evaluate函数,evaluate函数支持重载
Hive自定义函数部署运行: - 把程序打包放到目标机器上去
- 进入hive客户端,添加jar包:-hive>add jar /root/training/udfjar/udf_test.jar
- 创建临时函数:-hive>CREATE TEMPORARY FUNCCTION <函数名> AS ‘Java类名’
注意:临时函数的生命周期只在当前会话中。
Hive自定义函数的使用: - select <函数名> from table;
销毁临时函数: - hive>DROP TEMPORARY FUNCTION <函数名>;
hive的自定义函数案例
拼加2个字符串
ConcatString.java文件源代码:
package demo.udf;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
public class ConcatString extends UDF {
public Text evaluate(Text a,Text b){ //这里不能使用string,因为string不能在hadoop集群中进行通信
return new Text(a.toString() +"****" + b.toString());
}
}
之后导出成jar文件,上传到linux服务器上