文章目录

  • 1、系统内置函数
  • 2、自定义函数(UDF)(路径不唯一)
  • 3、压缩
  • 1)、开启Map输出阶段压缩
  • 2)、开启Reduce输出阶段压缩
  • 4、存储
  • 1)、列式存储和行式存储
  • 5、存储和压缩对比
  • 1)、比较各种存储格式
  • 2)、比较各种压缩格式
  • 6、Fetch抓取
  • 7、表的优化
  • 1)、小表大表join
  • 2)、大表大表join
  • 3)、笛卡尔积
  • 4)、行列过滤
  • 5)、动态分区★★★
  • 8、合理设置Map及Reduce数
  • 1)、复杂文件增加Map数
  • 2)、小文件进行合并
  • 3)、合理设置Reduce数


1、系统内置函数

--查看系统自带的函数
show functions;

--显示自带的函数的用法
desc function upper;

--详细显示自带的函数的用法
desc function extended upper;

2、自定义函数(UDF)(路径不唯一)

1)、创建一个Maven工程Hive

2)、导入依赖

<dependencies>
		<!-- https://mvnrepository.com/artifact/org.apache.hive/hive-exec -->
		<dependency>
			<groupId>org.apache.hive</groupId>
			<artifactId>hive-exec</artifactId>
			<version>3.1.2</version>
		</dependency>
</dependencies>

3)、创建一个类

package com.atguigu.hive;
import org.apache.hadoop.hive.ql.exec.UDF;

public class Lower extends UDF {

	public String evaluate (final String s) {
		
		if (s == null) {
			return null;
		}
		
		return s.toLowerCase();
	}
}

4)、打成jar包上传到服务器/opt/module/jars/udf.jar

5)、将jar包添加到hive的classpath

add jar /opt/module/datas/udf.jar;

6)、创建临时函数与开发好的java class关联

create temporary function mylower as "com.atguigu.hive.Lower";

7)、即可在hql中使用自定义的函数strip

select ename, mylower(ename) lowername from emp;

3、压缩

hive的默认压缩

hive> set mapreduce.map.output.compress.codec;
+---------------------------------------------------------------------------------+--+
|                                       set                                       |
+---------------------------------------------------------------------------------+--+
| mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.DefaultCodec  |
+---------------------------------------------------------------------------------+--+

1)、开启Map输出阶段压缩

1.开启hive中间传输数据压缩功能

hive (default)>set hive.exec.compress.intermediate=true;

2.开启mapreduce中map输出压缩功能

hive (default)>set mapreduce.map.output.compress=true;

3.设置mapreduce中map输出数据的压缩方式

hive (default)>set mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;

4.执行查询语句

hive (default)> select count(ename) name from emp;

2)、开启Reduce输出阶段压缩

1.开启hive最终输出数据压缩功能

hive (default)>set hive.exec.compress.output=true;

2.开启mapreduce最终输出数据压缩

hive (default)>set mapreduce.output.fileoutputformat.compress=true;

3.设置mapreduce最终数据输出压缩方式

hive (default)> set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;

4.设置mapreduce最终数据输出压缩为块压缩

hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;

5.测试一下输出结果是否是压缩文件

hive (default)> insert overwrite local directory  '/opt/module/datas/distribute-result' select * from emp distribute by deptno sort by empno desc;

4、存储

Hive支持的存储数据的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET。TEXTFILE和SEQUENCEFILE的存储格式都是基于行存储的;ORC和PARQUET是基于列式存储的

1)、列式存储和行式存储

hive加载gbk文件 hive gzip_大数据

左边为逻辑表,右边第一个为行式存储,第二个为列式存储

1.行存储的特点

查询满足条件的一整行数据的时候,列存储则需要去每个聚集的字段找到对应的每个列的值,行存储只需要找到其中一个值,其余的值都在相邻地方,所以此时行存储查询的速度更快。

2.列存储的特点

因为每个字段的数据聚集存储,在查询只需要少数几个字段的时候,能大大减少读取的数据量;每个字段的数据类型一定是相同的,列式存储可以针对性的设计更好的设计压缩算法。

但是在Hive的背景下,列存比较好

5、存储和压缩对比

1)、比较各种存储格式

--1、建立文本表格
create table log_text (
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as textfile;

--插入数据
load data local inpath '/usr/local/soft/hive-1.2.1/data/log.data' into table log_text;

--2、建立非压缩的orc格式
create table log_orc(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="NONE");

--插入数据
insert into log_orc select * from log_text;

--3、建立parquet格式
create table log_par(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as parquet;

--插入数据
insert into log_par select * from log_text;

三张表的大小分别为18.13MB、13.09MB、7.69MB

2)、比较各种压缩格式

--1、zlib压缩的orc格式
create table log_orc_zlib(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="ZLIB");

--插入数据
insert into log_orc_zlib select * from log_text;

--2、snappy压缩的orc格式
create table log_orc_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc
tblproperties("orc.compress"="SNAPPY");

--插入数据
insert into log_orc_snappy select * from log_text;

--3、snappy压缩的parquet格式
create table log_par_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as parquet
tblproperties("parquet.compression"="SNAPPY");

--插入数据
insert into log_par_snappy select * from log_text;

未压缩log_text大小7.69MB,压缩后两张表的大小分别为2.78MB(zlib)、3.75MB(snappy)

6、Fetch抓取

是指,Hive中对某些情况的查询可以不必使用MapReduce计算。

案例实操:

1)把hive.fetch.task.conversion设置成none,然后执行查询语句,都会执行mapreduce程序。

hive (default)> set hive.fetch.task.conversion=none;
hive (default)> select * from emp
hive (default)> select ename from 
hive (default)> select ename from emp limit 3;

2)把hive.fetch.task.conversion设置成more,然后执行查询语句,如下查询方式都不会执行mapreduce程序。

hive (default)> set hive.fetch.task.conversion=more;
hive (default)> select * from emp;
hive (default)> select ename from emp;
hive (default)> select ename from emp limit 3;

7、表的优化

1)、小表大表join

--建立大表
create table bigtable(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

--导入数据
load data local inpath '/usr/local/soft/hive-1.2.1/data/bigtable' into table bigtable;

--建立小表
create table smalltable(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

--导入数据
load data local inpath '/usr/local/soft/hive-1.2.1/data/smalltable' into table smalltable;
--建立结果表格
create table jointable(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

--连接操作
insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from smalltable s
join bigtable  b
on b.id = s.id;

insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable  b
join smalltable  s
on s.id = b.id;

2)、大表大表join

--建没有Null的表
create table ori(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

load data local inpath '/usr/local/soft/hive-1.2.1/data/ori' into table ori;

--建有Null的表
create table nullidtable(id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';

load data local inpath '/usr/local/soft/hive-1.2.1/data/nullid' into table nullidtable;
--空key过滤
insert overwrite table jointable select n.* from (select * from nullidtable where id is not null ) n  left join ori o on n.id = o.id;

--空key转换
insert overwrite table jointable
select n.* from nullidtable n full join ori o on 
nvl(n.id,rand()) = o.id;

3)、笛卡尔积

尽量避免笛卡尔积,join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积。

4)、行列过滤

列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。

行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。

5)、动态分区★★★

--设置非严格模式
set hive.exec.dynamic.partition.mode=nonstrict;
--创建分区表
create table dept_partition(id int, name string) partitioned
by (location int) row format delimited fields terminated by '\t';
--从原表中向分区表插入数据
insert into table dept_partition partition(location)
select deptno, dname, loc from dept;

8、合理设置Map及Reduce数

1)通常情况下,作业会通过input的目录产生一个或者多个map任务。

主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。

2)是不是map数越多越好?

答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。

3)是不是保证每个map处理接近128m的文件块,就高枕无忧了?

答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;

1)、复杂文件增加Map数

当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
增加map的方法为:根据computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M公式,调整maxSize最大值。让maxSize最大值低于blocksize就可以增加map的个数。

案例实操:

1.执行查询

hive (default)> select count(*) from emp;

Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1

2.设置最大切片值为100个字节

hive (default)> set mapreduce.input.fileinputformat.split.maxsize=100;

hive (default)> select count(*) from emp;

Hadoop job information for Stage-1: number of mappers: 6; number of reducers: 1

2)、小文件进行合并

(1)在map执行前合并小文件,减少map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。

set hive.input.format= org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

(2)在Map-Reduce的任务结束时合并小文件的设置:

在map-only任务结束时合并小文件,默认true

SET hive.merge.mapfiles = true;

在map-reduce任务结束时合并小文件,默认false

SET hive.merge.mapredfiles = true;

合并文件的大小,默认256M

SET hive.merge.size.per.task = 268435456;

当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge

SET hive.merge.smallfiles.avgsize = 16777216;

3)、合理设置Reduce数

1.调整reduce个数方法一

(1)每个Reduce处理的数据量默认是256MB

hive.exec.reducers.bytes.per.reducer=256000000

(2)每个任务最大的reduce数,默认为1009

hive.exec.reducers.max=1009

(3)计算reducer数的公式

N=min(参数2,总输入数据量/参数1)

2.调整reduce个数方法二

在hadoop的mapred-default.xml文件中修改

设置每个job的Reduce个数

set mapreduce.job.reduces = 15;

3.reduce个数并不是越多越好

1)过多的启动和初始化reduce也会消耗时间和资源;

2)另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;

在设置reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适;