Hive学习笔记一
1. Load的使用
//在1.x版本中定义long数据类型会报错(用bigint代替)
create table t_load_stu(name string,age bigint)
row format
delimited fields terminated by ',';
1.1本地在本地导入数据,本地数据不会删除(相当于复制)
//overwrite覆盖表中所有的数据
load data local inpath 文件路径 [overwrite] into table 表名
eg:load data local inpath '/root/apps/hive-data/local_load_stu.dat'
into table t_load_stu;
1.2在hadoop中导入数据,hadoop上的数据被删除(相当于剪切)
load data inpath hadoop上文件目录 into table tab_name
eg:load data inpath '/hivedata/load_stu.dat' into table t_load_stu;
load data inpath '/hivedata/load_stu.dat' overwrite into table t_load_stu;
2.Insert的使用
(1)创建源数据库
create external table org_stu(phone string,real_name string,age int,
gender int,country string,ip string,creat_time date,creator string)
row format
delimited fields terminated by ','
location '/hivedata';
//修改表中某个字段的类型
alter table org_stu change gender gender string;
//加入本地数据
load data local inpath '/root/apps/hive-data/org_stu.dat' into table org_stu;
(2)为查询出来的数据插入创建表
create table t_copy_stu1(phone string,real_name string,age int)
row format
delimited fields terminated by ',';
(3)创建分区表
create table t_copy_partition_stu(phone string,real_name string,ip string)
partitioned by(creat_time string)
row format
delimited fields terminated by ',';
(4)多重插入准备两张表
create table t_mult_stu_1(phone string,real_name string)
row format
delimited fields terminated by ',';
create table t_mult_stu_2(phone string,gender string,age int)
row format
delimited fields terminated by ',';
2.1将查询出来的结果插入到一个表中
语法:insert [overwrite]/into table 表名
select 字段 from 表名 where 条件
eg:insert overwrite table t_copy_stu1 select phone,real_name,age from org_stu;
2.2将查询出来的结果作为插入到表中的某个分区中(自动分区模式)
设置自动分区模式:set hive.exec.dynamic.partition.mode=true;
语法:insert overwrite table 表名 partition (分区字段名)
select 字段 from 表名 where 条件
eg:insert overwrite table t_copy_partition_stu partition(creat_time)
select phone,real_name,ip,substring(creat_time,0,10) as creat_time from org_stu;
2.3多重插入
语法:from 表名
insert into table 表名 select 字段名称 where 查询条件
...
eg:from org_stu
insert into table t_mult_stu_1 select phone,real_name
insert into table t_mult_stu_2 select phone,gender,age;
3Select
表:
create table t_stu_limit_20(sno int,name string,age int,sdp string)
row format
delimited fields terminated by ',';
注:1、set hive.exec.reducers.bytes.per.reducer=<number>,设置每个reducer最大处理的数据大小(单位:字节)来计算出需要多少个reducer去处理,默认大小是:256000000
2、set hive.exec.reducers.max=<number>,设置reducer的最大值,如果上面设置的算出来的reducer的个数超过max的值,以max的值为准.如果上面的计算出reudcer小于max,以小的为准。(默认值是:1009)
3、set mapreduce.job.reduces=<number>固定的设置reducer的个数
3.1 distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列算法
注:跟reducer的个数有关,不具有排序
eg:select * from t_stu_limit_20 distribute by sno;
3.2 sort by(字段) 不是全局排序,其在数据进入reducer前完成排序。
注:如果用sort by 进行排序并且设置mapred.reduce.tasks>1,则sort by 只能保证每个reducer的输出有序,不保证全局有序
eg:select * from t_stu_limit_20 distribute by sno sort by age;
3.3 order by(字段) 会对输入做全局排序
注:只有一个reducer,缺点是当输入规模较大时需要较长的计算时间
(Number of reduce tasks determined at compile time: 1)
eg:select * from t_stu_limit_20 order by age;
3.4 cluster by(字段) 除了具有distribute by 功能外还可以对该字段进行排序
注:如果分桶和sort是同一个字段,此时cluster by =distribute by +sort by
eg:insert overwrite local directory '/root/test' select * from t_stu_limit_20 cluster by sno;
分桶的作用:最大的作用是用来提高join操作的效率
补充:如何才能在yarn的管理控制台上查看已经完成的job信息?
需要在hadoop集群上启动jobhistory服务器,执行的命令是:mr-jobhistory-daemon.sh start
historyserver
4 join
注:
1)目前hive只支持等值得join,不支持非等值的连接,因为非等值join很难转化为map/reducer任务
2)可以join多于2个表,执行流程分析
情况一:如果join多个表时,join key 是同一个,则join会被转化为单个map/reduce任务
eg:select a.val,b.val,c.val from a join b on(a.key=b.key1) join c
on (c.key=b.key1)
情况二:如果join key非同一个,则join会被转化为多个map/reduce的任务
eg:select a.val,b.val,c.val from a join b on(a.key=b.key1) join c
on(c.key=b.key2)
分析:join被转化为2个map/reduce任务。因为b.key1用于第一次join条件,而b.key2用于第二次join.
3)join时,每次map/reduce的任务逻辑
说明:reducer会缓存join序列中除了最后一个表所有表的记录,再通过最后一个表将结果序列化到文件系统中。
优点:这一实现有助于在reduce端减少内存的使用量。
注:在实践中应该把最大的那个表放在最后,否则会因为缓存浪费大量的缓存。
eg:1)select a.val,b.val,c.val from a join b on(a.key=b.key1) join c
on (c.key=b.key1)
说明:所有的表都使用同一个join key(使用一次map/reduce任务计算)。reduce端会缓存a表和b表的记录,然后每次取得一个c表记录就计算一次join结果。
2)select a.val,b.val,c.val from a join b on(a.key=b.key1) join c
on(c.key=b.key2)
说明:join key不同,这里用了2次map/reduce任务。第一次缓存a表用b表序列化,第二次缓存第一次map/reduce任务的结果,然后用c表序列化。
4)LEFT、RIGHT、FULL 、OUTER关键字用于处理join中空记录的情况
说明:和数据库处理的差不多
5)join发生在where字句之前
实际场景问题:select a.val,b.val from a left outer join(a.key=b.key) where a.ds='2016-12-30' and b.ds='2016-12-30'
问题描述:如果b找不到对应的a表的记录,b表所有列都会列出null,包括ds列。也就是说join会过滤b表中不能找到匹配a表join key的所有记录,导致LEFT OUTER与where子句无关。
解决方案:在left out时使用条件
select a.val,b.val from a left outer join on(a.key=b.key and b.ds='2016-12-29' and a.ds='2016-12-29')
说明:这一查询的结果是预先在join阶段过滤的,所以不会存在上述的问题。这一逻辑可以用于right 和full类型的join中。
6)join是不能交换位置的
说明:无论是left还是right都是通过左连接的。
eg:select a.val1,a.val2,b.val,c.val from a join b on(a.key=b.key) left outer join c on(a.key=b.key)
分析:先join a表到b表的记录,丢弃掉所有join key中不匹配的记录,然后用这中间结果和c表做join.也就是说,就是当一个key在a表和c表都存在,但在b表不存在的时候,整个记录在第一次join,即a join b的时候被丢弃掉了(包括a.val1,a.val2和a.key),然后我们在跟c表join的时候,如果c.key与a.key或b.key相等,就会得到这样的结果:null,null,null,c.val
5hive参数配置
5.1hive的命令行
语法结构:
hive [-hiveconf x=y]*[<-i filename>]*[<-f filename>|-e query-string][-s]
说明:
1、-i从文件中初始化hql;
2、-e从命令行执行指定的hql
3、-f执行hql脚本
4、-v输出执行的hql语句到控制台
eg:命令:hive -e 'use db2;select * from t_load_stu';
结果:Time taken: 1.02 seconds
OK
zs 12
ls 15
wu 16
5.2参数配置方式
1)配置文件(全局有效)
说明:用户自定义配置文件:hive-site.xml
默认配置文件:hive-default.xml
注: 1>用户自定义配置文会覆盖默认配置;
2>hive会读取hadoop的配置,因为hive作为hadoop的客户端启动的,hive配置会覆盖hadoop的配置
2)命令行参数(对hive启动实例有效)
说明:-hiveconf param=value
eg:-hiveconf hive.root.logger=info,console
3)参数声明(对hive的连接session有效)
说明:可以在hql中使用set关键字来设定参数
eg:1>set hive.exec.reducers.bytes.per.reducer=>每个reduce task的平均负载数据量,hive会估算我们的总数据量,然后用总数据量除以上述参数值,就能得到需要运行的reduce task的数量
2>set hive.exec.reducers.max=>设置reduce task的上限
3>set mapreduce.job.reduces=>指定固定的reduce task的数量
注:这个参数在必要时<业务逻辑决定只能用一个reduce task>会忽略的(例如order by)
6hive函数
创建测试需要的表,方便函数的测试
1、create table dual(id string);
2、load一个文件(一行,一个空格)到dual表中
6.1自定义hive的函数(基于java开发语言)
步骤:第一步:先开发一个java类,继承UDF,并重载evaluate方法;
第二步:打成jar包上传到服务器;
第三步:将jar包添加到hive的classpath(命令:add jar jar包的全路径);
第四步:创建临时函数与开发好的java class关联(命令:create temporary function 方法名称 as '定义方法类名的全路径');
eg:
1)创建一个java类,集成UDF
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.hive.ql.exec.UDF;
public class MyHiveFunctionUdf extends UDF {
// 重载方法
public String evaluate(String inStr) {
if (StringUtils.isEmpty(inStr)) {
return inStr;
}
return inStr.toLowerCase();
}
public int evaluate(Integer... sumParams) {
if (sumParams == null || sumParams.length == 0)
return 0;
int totalValue = 0;
for (Integer sumParam : sumParams) {
if (sumParam != null) {
totalValue += sumParam;
}
}
return totalValue;
}
public String evaluate(String... inStrs) {
StringBuffer sb = new StringBuffer();
if (inStrs == null || inStrs.length == 0) {
return "";
}
for (String inStr : inStrs) {
sb.append(inStr);
}
return sb.toString();
}
}
2)打成jar添加到hive的classpath中去
命令:hive> add jar /root/hive-udf.jar;
结果:Added [/root/hive-udf.jar] to class path(加载本地的classpath)
Added resources: [/root/hive-udf.jar](加载到distribute cache中分发到各个map/reduce中)
3)创建临时函数myfuns与com.hive.udf.MyHiveFunctionUdf类映射
命令:create temporary function myfuns as 'com.hive.udf.MyHiveFunctionUdf';
结果:OK
Time taken: 1.194 seconds
4)在hql中使用函数
命令:select myfuns('1','2','3') from dual;
结果:123
命令:select myfuns(1,2) from dual;
结果:3
6.2Transform实现hive自定义的函数
说明:hive的transform关键字提供了在sql中调用自写脚本的功能
eg:
1、创建容纳json数据的表
create table t_json(json_line string)
row format
delimited fields terminated by '\001';
2、使用get_json_object对json表中的json字符串进行解析并保存到新的表中
create table t_rating
as select get_json_object(json_line,'$.movie') as movieid,
get_json_object(json_line,'$.rate') as rate,
get_json_object(json_line,'$.timeStamp') as timestring,
get_json_object(json_line,'$.uid') as userid
from t_json
3、通过transform方式创建通过时间戳获取weekday
python的脚本:
#!/bin/python
import sys
import datetime
for line in sys.stdin:
line = line.strip()
movieid, rating, unixtime,userid = line.split('\t')
weekday = datetime.datetime.fromtimestamp(float(unixtime)).isoweekday()
print '\t'.join([movieid, rating, str(weekday),userid])
创建一张记录表:
CREATE TABLE u_data_new (
movieid INT,
rating INT,
weekday INT,
userid INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
命令:add file /root/apps/hive-data/weekday-mapper.py(向每个map/reduce发送该脚本)
执行:
INSERT OVERWRITE TABLE u_data_new
SELECT
TRANSFORM (movieid , rate, timestring,userid)
USING 'python weekday-mapper.py'---使用脚本函数
AS (movieid, rating, weekday,userid)
FROM t_rating;
校验是否成功:
select distinct(weekday) from u_data_new limit 10;
7hvie特殊分割符处理
hive读取数据的机制:1、首选用InputFormat<默认是:org.apache.hadoop.mapred.TextInputFormat>的具体实现类读入文件数据,返回一条一条的记录(可以是行或自定义逻辑中的行)
2、然后用SerDe<默认是:org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe>的一个具体实现类,对上面返回一条一条的记录进行字段切割
7.1通过自定义InputFormat解决特殊分隔符的问题
eg:
1、原始数据格式:zs||24
ls||27
2、重写InputFormat
import java.io.IOException;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapred.InputSplit;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.LineRecordReader;
import org.apache.hadoop.mapred.RecordReader;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapred.TextInputFormat;
import com.google.common.base.Charsets;
public class TextInputFormatWrapper extends TextInputFormat {
@Override
public RecordReader<LongWritable, Text> getRecordReader(InputSplit genericSplit, JobConf job, Reporter reporter) throws IOException {
reporter.setStatus(genericSplit.toString());
String delimiter = job.get("textinputformat.record.delimiter");
byte[] recordDelimiterBytes = null;
if (null != delimiter) {
recordDelimiterBytes = delimiter.getBytes(Charsets.UTF_8);
}
LineRecordReader lineRecordReader = new LineRecordReader(job, (FileSplit) genericSplit, recordDelimiterBytes);
return new LineRecordReaderWrapper(lineRecordReader);
}
public static class LineRecordReaderWrapper implements RecordReader<LongWritable, Text> {
private LineRecordReader lineRecordReader;
public LineRecordReaderWrapper(LineRecordReader lineRecordReader) {
super();
this.lineRecordReader = lineRecordReader;
}
@Override
public void close() throws IOException {
lineRecordReader.close();
}
@Override
public LongWritable createKey() {
return lineRecordReader.createKey();
}
@Override
public Text createValue() {
return lineRecordReader.createValue();
}
@Override
public long getPos() throws IOException {
return lineRecordReader.getPos();
}
@Override
public float getProgress() throws IOException {
return lineRecordReader.getProgress();
}
@Override
public boolean next(LongWritable key, Text value) throws IOException {
boolean hasNext = lineRecordReader.next(key, value);
if (hasNext && value != null) {
String replaceResult = value.toString().replaceAll("\\|\\|", "\\|");
value.set(replaceResult);
}
return hasNext;
}
}
}
3、创建表使用该InputFormat
create table t_bi(name string,age int)
row format delimited fields terminated by '|'
stored as inputformat 'com.hadoop.extend.TextInputFormatWrapper'
outputformat 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat';
4、加载数据
load data local inpath '/root/apps/hive-data/bi.dat' into table t_bi;
5、测试结果是
select * from t_bi;
zs 24
ls 27
7.2使用RegexSerDe通过正则表达式来抽取字段
eg:
1、 创建表,使用serde为org.apache.hadoop.hive.serde2.RegexSerDe
create table t_bi_reg(name string,age int)
row format
serde 'org.apache.hadoop.hive.serde2.RegexSerDe'
with serdeproperties(
'input.regex'='(.*)\\|\\|(.*)',
'output.format.string'='%1$s %2$s'
)
stored as textfile;
2、加载数据
load data local inpath '/root/apps/hive-data/bi.dat' into table t_bi_reg;
3、测试结果是:
select * from t_bi_reg;
zs 24
ls 27
注:在数据量大的情况下上述方式比该方式效率高
Hive学习笔记一的更多相关文章
- hive学习笔记之一:基本数据类型
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之三:内部表和外部表
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之四:分区表
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之五:分桶
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之六:HiveQL基础
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之七:内置函数
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之九:基础UDF
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- hive学习笔记之十:用户自定义聚合函数(UDAF)
欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<hive学习笔记>的第十 ...
- hive学习笔记之十一:UDTF
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- Hive学习笔记(一)
摘要: Hive 是建立在 Hadoop 上的数据仓库基础构架.它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储.查询和分析存储在 Hadoop 中的大规模数据的机制.H ...
随机推荐
- LeetCode – Group Shifted Strings
Given a string, we can "shift" each of its letter to its successive letter, for example: & ...
- Java基础五(方法)
今日内容介绍1.方法基础知识2.方法高级内容3.方法案例 ###01方法的概述 * A: 为什么要有方法 * 提高代码的复用性 * B: 什么是方法 * 完成特定功能的代码块. ###02方法的定义格 ...
- linux——git安装使用
系统环境centos7 安装git命令 yum install git -y 安装好之后使用命令查看git版本 git –version [root@bogon ~]# git --version g ...
- react-static 基于react 渐进式静态站点生成框架
react-static 是一个不错的基于react 开发的静态站点生成框架,可以用来替代create-react-app 包含的特性 100% react 很快的构建以及性能 自动代码以及数据分离 ...
- MySQL联结查询和组合查询
联结查询 1.关系表 主键:一列或一组列,能够唯一区分表中的每一行,用来表示一个特定的行 外键:为某个表中的一列,包含另一个表的主键,定义量表的关系. 2.创建联结 规定要连接的表和他们如何关联即可 ...
- HappytimeOnvif Client V8.3的使用
1.system-->system settings-->勾选RTP RTSP 2.start video poll
- java 中,for、for-each、iterator 区别
java 中,for.for-each.iterator 区别: 无论是在数组中还是在集合中,for-Each加强型for循环都是它们各自的普通for循环的一种"简写方式",即两者 ...
- Reshape以及向量机分类学习和等高线绘制代码
首先科普一下python里面对于数组的处理,就是如果获取数组大小,以及数组元素数量,这个概念是不一样的,就是一个size和len处理不用.老规矩,上代码: arr2 = np.array([-19.5 ...
- golang gorilla websocket例子
WebSocket协议是基于TCP的一种新的网络协议.它实现了浏览器与服务器全双工(full-duplex)通信--允许服务器主动发送信息给客户端. WebSocket通信协议于2011年被IETF定 ...
- Linux paste命令详解
Linux paste命令 Linux paste命令用于合并文件的列.paste指令会把每个文件以列对列的方式,一列列地加以合并 将每个指定文件里的每一行整合到对应一行里写到标准输出,之间用制表符分 ...