Hive基础知识记要 (三)

关于内置函数的核心使用策略:
1、查看有那些内置函数
show functions;

2、查看某个函数的具体使用手册
	desc function extended substring;

3、编写测试用例
	select xxxx();

特殊的常用的内置函数:

substring instr concat split 
length size array_contains
max min distinct avg sum count
explode
if  nvl  coalesce

两大类型:
1、关于日期时间的
2、关于字符串的操作

内置函数的练习,学习使用的过程中:

内置函数:
	hive-1.x版本:216个
	hive-2.x版本:271个

但是 不管定义多少个内置函数,肯定没法满足所有任意场景的使用

面试常见的问题:
	你在工作当中,有定义过哪些自定义函数呢?
	1、内置函数有271个,我能定义一个和这271个中的某一个是实现相同功能的么?
		split  concat  ..... 
	2、内置函数可以嵌套使用
		xx1(xx2(xx3(), xx4()))

show functions;

自定义: User Defined Function

UDAF:  aggregate	聚合函数
		max min sum count distinct avg
UDTF: table		表格生成函数
		explode
		接收的参数:
		1、array	多行
		2、map		多行2列

通用的思维

责任链  设计模式

原来写MR程序:  实现接口
class MyMapper implements org.apache.hadoop.mapreduce.mapred.Mapper<>

从hadoop0-2.x版本开始不一样:
现在写MR程序:	继承实现类
class MyMapper extends org.apache.hadoop.mapreduce.Mapper<>
	setup  默认实现: // do nohting 
	map		原来是抽象方法,现在是实现方法
	cleanup	默认
	run
	多增加了三个方法:
		setup  cleanup  run 

	void run(Context context){
		setup(context)
		// context里面装包了一个对象:recordReader
		while(context.nextKeyValue()){
			map(context.getCurrnetKey(), context.getCurrnetValue(), context)
		}
		cleanup(context)
	}

知识:基本上,各种java技术组件都在这么进化
	原来都是:实现接口
	现在都是:利用继承

Storm 
	interface Spout
	interface Bolt

	extends RichSpout
	extends RichBolt

	@override 重写

技术组件中的使用方式:
1、能尽量减轻用户的负担,就别让用户去写
	提供了一个接口,
	同时也提供一些实现类(默认使用组件,要么提前帮忙实现好一部分业务代码)

2、先指定规范,然后提供一部分常见的实现,另外的比较特殊的实现,全部交给用户自己做
	hive的内置函数:
	1、提供了常见 271个内置函数
	2、提供了一个规范,可以让用户自己去写函数


do(Animal a)

class Male implements Sex
class Female implements Sex

do(Sex sex)

class SS implements Sex


创建临时函数

实现一些比较复杂的字段数据的处理
1、内置函数
2、自定义函数
UDF
UDAF
UDTF

如果会把数据存储到Hive,使用的方式:load / insert / hadoop fs -put
集群的运维,其他的开发,测试,DBA

如果让使用内置函数不能满足要求,去使用自定义函数,需要编写java代码
用户体验不好,适用性不好。

提供了一种技术:
函数的概念:我给你一堆数据,你给我一堆数据。
你给我把数据进行处理

内置函数
自定义函数

hive的使用者:
运维,测试,DBA

写shell python ruby等等的脚本

hive的SQL语句中,去调用运维写的脚本如何?
如果可以的话,那么hive的使用群体,扩宽了。

脚本:解释型的编程语言编写的代码
java class:  编译型的编程的语言

hive缇欧刚了一种技术:
transform
外带的脚本程序 shell python

需求:
统计每部电影被多少人看了。

{
“movie”: “2398”,
“rate”: “4”,
“timeStamp”: “978302281”,
“uid”: “1”
}

2398,4,978302281,1

数据存储在:
/hive1904/jsontest/rating.json

创建原始表:
create external table rate_json(line string) row format delimited location “/hive1904/jsontest/”;

创建解析结果出来的表:
create table rate(movie int, rate int, unixtime int, userid int) row format delimited fields terminated by ‘\t’;

解析语句:
insert into table rate
select
get_json_object(line, ‘ . m o v i e ′ ) a s m o v i e , g e t j s o n o b j e c t ( l i n e , ′ .movie') as movie, get_json_object(line, ' .movie)asmovie,getjsonobject(line,.rate’) as rate,
get_json_object(line, ‘ . t i m e S t a m p ′ ) a s u n i x t i m e , g e t j s o n o b j e c t ( l i n e , ′ .timeStamp') as unixtime, get_json_object(line, ' .timeStamp)asunixtime,getjsonobject(line,.uid’) as userid
from rate_json;

需求:
统计每部电影被多少人看了。
select movie, count(userid) as total from rate group by movie order by total desc limit 3;

set hive.exec.mode.local.auto=true;

get_json_object怎么使用

weekday_mapper.py:python文件的功能:

你给我一行数据:
输入
2398	4	978302281	1
这个脚本就处理成:
输出
2398	4	2		1

最后的实现:

创建表:lastjsontable
create table lastjsontable(movie int, rate int, weekday int, userid int) row format delimited fields terminated by ‘\t’;
create table rate(movie int, rate int, unixtime int, userid int) row format delimited fields terminated by ‘\t’;

解析数据:
insert into table lastjsontable
select transform(movie,rate,unixtime,userid)
using ‘python weekday_mapper.py’
as(movie,rate,weekday,userid)
from rate;

总结:
如果你编写SQL的过程中,遇到了一种情况:
需要结合函数来实现一些复杂的数据处理:

三种方式:
1、271个内置函数
2、提供了一种通用的模式:自定义函数
3、提供了一种技术:transform的方式来调用外部的一个处理脚本
	python weekday_mapper.py
	sh myweekday.sh

01||huangbo||19
02||xuzheng||20
03||wangbaoqiang||21

01_huangbo_19
02_xuzheng_20
03_wangbaoqiang_21

hive的官网直接告诉我们:分割符:是 char 不是 string

SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
由于默认的SerDe组件:序列化 和 反序列 组件
LazySimpleSerDe不支持使用多字节的分隔符

RegexSerDe 正则匹配

(.)_(.)_(.*)

IT技术界通用的三大技术:
json
jackson
fastjson
gson
正则

xml
	dom4j
	sax4j

create table mydata2(id string, name string)
row format serde ‘org.apache.hadoop.hive.serde2.RegexSerDe’
with serdeproperties(‘input.regex’=’(.)\|\|(.)’,‘output.format.string’=’%1 s s %2 ss’)
stored as textfile;

TextInputFormat里面有两个重要的方法:
逻辑切片
List getSplits(JobContext job);

获取RecordReader对象
public RecordReader<LongWritable, Text> 
createRecordReader(InputSplit split, TaskAttemptContext context)

	nextKeyValue()
	getCurrnetKey()
	getCurrentValue()

hive shell

进入hive之后的

quit 退出客户端的
set key=value 在hive的客户端 进行设置参数
hive-default.xml
set hive.exec.mode.local.auto=true;
只对当前客户端生效 重新进入客户端 重新设置
set key 在hive的客户端查询参数对应的值
set hive.exec.mode.local.auto;
set -v 打印所有的hive的参数
add FILE [file] 添加文件到hive的classpath下的
add jar 添加jar hive的classpath 下的
list FILE 显示所有的文件
list jar|jars 显示所有的jar
! [cmd] 在hive的客户端执行linux的命令 查看 创建 但是切换不可以支持
dfs [dfs cmd] dfs -ls cat 在hive执行hadoop命令
hadoop fs - 旧
hdfs dfs - 新
hadoop|hdfs 启动hadoop|hdfs的客户端
fs|dfs 连接hadoop的文件系统
hive>

[query] hql 查询
source FILE 在hive客户端 加载sql脚本
shell 脚本 shell 命令组成的 条件判断 循环
sql脚本 一系列sql组成的

transform
hive中解析脚本

进入hive之前的

hive [-hiveconf x=y]* [<-i filename>]* [<-f filename>|<-e query-string>]

设置参数
1)hive -hiveconf key=value 一次只能允许设置一个参数
hive -hiveconf hive.exec.mode.local.auto=true
启动hive客户端的同事 设置参数

2)-i 文件 通过一个文件 初始化所有参数 可以一次性设置多个参数 init
启动hive的时候 通过文件 初始化多个参数

执行sql语句
-f file
hive -f /home/hadoop/tmp_data/my.sql
启动客户端
执行脚本 source
退出客户端

-e
hive -e sql 语句
hive -e “show databases;”
hive -e “select * from test_shell.stu”
先进入hive客户端 执行sql语句 退出客户端

hive的转换流程

explain sql 查看sql语句的执行计划
explain
select
dept,avg(age) avg_age
from stu
group by dept
order by avg_age desc limit 1;
stage1: group by + avg mapreduce
stage2: order
stage0:limit 1
Operator 操作符
hive本质 将hql语句转换为一个个的hql的操作符 操作符根据语句的关键词提取的 select ,group by,聚合函数,order by ,limit,having
Operator操作符:
1)mapreduce操作 group by
2)hdfs的读写操作 fetch Operator hdfs

hive的典型语句 如何转换mr的
1)group by +聚合函数
map端:
key: group by 的字段
value:需要聚合的字段
shuffle:
combiner
reduce端:
相同的一组的数据 分到一起
求聚合结果 sum|avg|max|min
默认 group by +聚合函数一起使用 有优化的
在map端执行combiner

2)order by 全局排序的
select * from stu order by age desc;
set numreducetasks=3;
part-r-00000 34—25
part-r-00001 24—18
part-r-00002 <18
map端:
key:-age
value: 其他字段
shufle:
定义分区
34—25 0
24—18 1
《18 2
reduce:
直接输出

sort by 局部排序的
set numreducetasks=3;
select * from stu sort by age desc;
map
key: -age
value:其他
shuffle:
默认分区
每一个分区 排序
reduce:直接输出

3)join
默认情况下 join过程 执行的 mapjoin | reduce join
在hive中 默认有一个表是小表时候 执行的mapjoin
小表判断依据:
小表大小: set hive.mapjoin.smalltable.filesize=25000000; 23.8M
在hive中 较小表不超过23.8M 都是执行的map join

mapjoin :
将一个小表 加载到缓存中 读取到内存中map
map端 map函数 读取另一个大表 进行关联

reduce join :
将两表关联的 关联键 作为map输出的key 对输出的value打标记 标记数据来源
reduce端 接受所有关联键的两表数据 可以进行关联了
大 数据倾斜

4)count(distinct …)
distinct 字段
select distinct dept from stu;
CS MA IS
map端:
key:dept 需要去重的字段
value:null
reduce端:
需要去重的字段 分到一组
key 默认的一组 第一个
values null null null

hive数据倾斜 *****

hive的数据倾斜 mr的数据倾斜 reducetask 数据倾斜
不容易产生数据倾斜的情况:
1)map join
2) sum|max|min + group by
有combiner
3)不转换为mr任务的
Operator MR|HDFS
fetch Operator
哪些操作不执行mr的:
hive.fetch.task.conversion
none : 这个参数禁用
所有的查询 都来执行mr
minimal:
0.10—0.13
SELECT *,
where 字段分区字段,
LIMIT
不执行mr的
more 默认
SELECT 原始字段,
FILTER where ,
LIMIT

容易产生数据倾斜的
1)reduce join
2)group by 不和聚合函数一起
3)count(distinct )

典型场景分析:

join 过程 reduce join
1)大量的关联键为null值的时候
users 用户表 UserId address 10G
logs 日志表 所有用户浏览网站的信息 UserId null
500G 250G
select * from users a join logs b on a.UserId=b.UserId;
map
key:
UserId
value: 标识+其他
shuffle:
分区 null 其他
排序
分组

reduce:
一个分区— reducetask
null 其他 — 1个reducetask中 260G
for(){
for(){

        }
    }
9reducetask ---1个28G      ---   250G 

解决:
1)将null值分散到多个reducetask中
null+随机数
null123
null234
select
*
from users a join logs b on a.UserId=nvl(b.UserId,b.UserId+rand())

2)null 值不参与关联  最后将null值  拼接到最后  推荐
select 
* 
from users a join 
(
select * from logs where UserId is not null 
) b 
on a.UserId=b.UserId 
union 
select "","","",* from logs where UserId is null;

2)关联键 类型不统一
users UserId int 133
logs UserId string 133 =null
select * from users a join logs b on a.UserId=b.UserId;

解决方案:
修改数据类型 将数据类型统一
select * from users a join logs b on a.UserId=trim(b.UserId);

3)大
reduce join
key值分布不均匀 分区数据不均匀 数据倾斜
hive中的所有类型join方案
1.小
小 mapjoin
2.大小(《23.8M ) mapjoin
3.大
中(>23.8M 内存能够承受)
默认执行reduce join 数据倾斜的
为了效率 也为了解决数据倾斜 强制执行mapjoin
/+mapjoin(需要强制加载到内存中的小表)/
users 1G
logs 1T
select
/+mapjoin(a)/*
from users a join logs b on a.UserId=b.UserId;
4.大大 (这两个表 都无法放在内存的)
users 500G 用户表 每当有一个用户注册 一条数据
500000000用户
40w
logs 1T 日志表 每一个点击行为 一条数据 一天分析一次
40w
select * from users a join logs b on a.UserId=b.UserId;
解决方案:
对其中一个表 瘦身
对users 表进行瘦身 只需要过滤出来 logs表能够关联的userid
1)求logs表中有哪些useriD
SELECT distinct UserId from logs;
2)对users表进行瘦身
create table users_final as
select
/
+mapjoin(a)/b.
from (
SELECT distinct UserId from logs
) a join users b on a.UserId=b.UserId;
users 最终需要的
3)进行真正的关联
select
/+mapjoin(a)/*
from users_final a join logs b on a.UserId=b.UserId;
分桶表 一般不用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值