Hive优化笔记

2021-03-11  本文已影响0人  zhglance

1.hive参数优化

1.1 map个数优化

map的个数是如何决定的:

mapred.min.split.size: 数据的最小分割单元大小,默认值是1B
mapred.max.split.size: 数据的最大分割单元大小,默认值是256MB

一个文件在执行数据处理的时候,被分成文件的个数如下:

if(一个文件的大小 <= mapred.max.split.size) {
     该文件生成一个map
} else {
     一个文件的产生的map的个数 = (文件大小 / mapred.max.split.size) + 1
}

1.1.1 减少map个数:

set mapred.max.split.size=256000000;  //  -- 决定每个map处理的最大的文件大小 单位为B
set mapred.min.split.size.per.node=100000000;//每个节点处理的最小split
set mapred.min.split.size.per.rack=100000000;//每个机架处理的最小slit
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;// 默认开启

1.文件大于256MB的进行分割;
2.那些小于256MB的(包括分割大文件剩下的)进行合并;

备注:
a.四个参数的配置结果大小要满足如下关系。
max.split.size >= min.split.size >= min.size.per.node >= min.size.per.node

b.四个参数的作用优先级分别如下
max.split.size <= min.split.size <= min.size.per.node <= min.size.per.node

1.1.2 增加map的个数

a.调节mapred.max.split.size的大小可以达到调整map个数的效果,直接调整mapred.map.tasks这个参数是没有效果的。
b.拆分文件
如果一个文件为100MB,属性字段很少,结果数据量却很大(如1000万),使用a方案任然生成一个map,那么可以手动将文件拆分成多个。

set mapred.reduce.tasks=100;
  create table tableName_1 as 
  select * from tableName t
  distribute by rand(t.name);
set mapred.max.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

1.2 reduce个数优化

多少个reduce产生多少个输出文件,reduce个数过大会产生过多的小文件,reduce的启动和销毁也会带来消耗;reduce个数过小,单个reduce处理的数据量过大会导致OOM。

set mapred.reduce.tasks/mapreduce.job.reduces=100
set hive.exec.reducers.bytes.per.reducer = 256123456// 每个reduce处理的数据量,默认为1GB
set hive.exec.reducers.max=1009 // 每个任务最大的reduce数,默认为1009
//如果不设置,hive会根据输入文件估算reduce的个数

2.压缩优化

hive底层使用mapreduce来实现,而mapreduce的中间过程都需要落入磁盘,消耗大量的网络IO和磁盘IO,因此针对IO密集型job,通过增加CPU资源消耗来降低IO资源的消耗,达到提高性能的目的。

压缩方式:

序号 压缩格式 是否可split 是否自带 压缩率 速度 是否Hadoop自带 对应class
1 gzip 很高 比较快 org.apache.hadoop.io.compress.GzipCodec
2 lzo 比较高 很快 否,需要安装 org.apache.hadoop.io.compress.LzoCodec
3 snappy 比较高 很快 否,需要安装 org.apache.hadoop.io.compress.SnappyCodec
4 bzip2 最高 org.apache.hadoop.io.compress.BZip2Codec

3.存储优化

序号 存储格式 行列方式 说明
1 TextFile 行式存储
2 Sequence Files 行式存储 支持Block压缩
3 RCFile 按行分块,按列存储 结合了行存储和列存储的优点
4 ORCFile 按行分块,按列存储 RCFile的改良版本
5 parquet 行式存储

一般选择ORCFile/parquet + snappy 的方式

4.表结构

4.1 内部表和外部表

创建表的时候指定external就是外部表,否则就是内部表。

序号 表类型 管理方 数据存储位置 元数据 修改表结构
1 内部表 Hive自身管理 /user/hive/warehouse 内部表删除后元数据和数据都删除 直接同步到元数据
2 外部表 HDFS管理 用户自己通过location指定 外部表删除后只删除元数据,不删除hdfs数据 需要msck repair table tableName 进行同步到元数据

4.2 静态分区和动态分区

静态分区在建表的时候通过PARTITIONED BY定义分区,alter table 添加和删除分区

动态分区:

set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;

4.2 分桶

分桶通过指定列的数据取hash值将数据进行划分,相同的数据划分到一个桶里,从而减少数据访问量,提高查询效率。

set hive.enforce.bucketing = true
CLUSTERED BY (id) INTO 200 BUCKETS  //分桶的列id是表中已有的列

5.sql优化

5.1 小表放到join左边:

将数据量小的表或子查询放在join的左边,因为join操作的reduce阶段,将join左边的表的内容加载进内存,因此将数据量小的表放在左边,可以提高效率,一定程度避免OOM。

5.2 过滤放到关联之前

列过滤:只select需要的字段
行过滤:过滤条件放到子查询里

5.3 开启mapjoin

set hive.auto.convert.join = true
set hive.mapjoin.smalltable.filesize=25123456 // 触发mapjoin的小文件大小的阈值

不指定mapjoin开启的情况,hive会把所有join转换为common join,即mapreduce的时候执行join,可以使用mapjoin将小文件的整个数据加载到内存,在map端进行join,避免reduce处理,一定程度上避免了数据倾斜。

5.4 开启map端聚合

默认情况下,map阶段同一key数据分发给一个reduce,当一个key数据过大时就倾斜了。不是所有的聚合操作都必须在reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在reduce端得出最终结果。

set hive.map.aggr = true; // 默认true
 set hive.groupby.mapaggr.checkinterval = 100000; // 在Map端进行聚合操作的条目数目
 set hive.groupby.skewindata = true; // 有数据倾斜的时候进行负载均衡,默认false

5.5 使用先GROUP BY再COUNT的方式替换COUNT DISTINCT

数据量大的情况下,由于COUNT DISTINCT操作需要用一个reduce task来完成,这一个reduce需要处理的数据量太大,容易产生倾斜问题。

5.6 查看执行计划

explain sql // 查看执行计划
explain extended // 查看详细执行计划

6.其他优化

6.1 Fetch抓取

fetch抓取开启一定程度上可以避免触发mapreduce,主要针对全局查找(select *),字段查找(select field),limit(limit 100)等
开启方式:

set hive.fetch.task.conversion=more  //关闭:none, 开启(默认):more

6.2 执行模式

6.2.1 本地模式
set hive.exec.mode.local.auto=true

主要针对小数据量和测试使用,即在单台机器上处理所有任务,避免在Hadoop集群上启动耗时的问题。

6.2.2 并行模式
set hive.exec.parallel=true  //或者通过配置文件来完成,非相互依赖的阶段并行执行,否则默认情况下,Hive一次只会执行一个阶段。
6.2.3 严格模式
set hive.mapred.mode=strict  // 默认关闭

对于分区表,禁止不指定分区查询
order by 必须有limit
禁止笛卡尔积查询

6.3 JVM重用

set  mapred.job.reuse.jvm.num.tasks=15;

JVM重用可以使得JVM实例在同一个job中重新使用N次,N值可配置,通常在10~20之间,也可在mapred-site.xml文件中。

<property>
  <name>mapreduce.job.jvm.numtasks</name>
  <value>15</value> 
</property>

缺点:JVM不是立即销毁,空闲的时候会导致资源浪费。

参考资料:

1.https://my.oschina.net/u/4351661/blog/4268581

上一篇下一篇

猜你喜欢

热点阅读