Hive调优分类

1、数据的压缩与存储格式

对分析的数据选择合适的存储格式与压缩方式能提高hive的分析效率

压缩方式

压缩可以节约磁盘的空间,基于文本的压缩率可达40%+; 压缩可以增加吞吐量和性能量(减小载入内存的数据量),但是在压缩和解压过程中会增加CPU的开销。所以针对非计算密集型的jobs可以使用压缩的方式提高性能。 几种压缩算法:

ORC和parquet格式最常用

注意:选择压缩算法的时候需要考虑到是否可以分割,如果不支持分割(切片的时候需要确定一条数据的完整性),则一个map需要执行完一个文件,如果文件很大,则效率很低。一般情况下hdfs一个块(128M)就是一个map的输入切片,而block是按物理切割的,可能一条数据会被切到两个块中去,而mapde 切片如何确保一条数据在一个切片中就需要看压缩算法是否支持分割。

存储格式(行存与列存)

1. TextFile

Hive数据表的默认格式,存储方式:行存储。 可以使用Gzip压缩算法,但压缩后的文件不支持split 在反序列化过程中,必须逐个字符判断是不是分隔符和行结束符,因此反序列化开销会比SequenceFile高几十倍。

2.Sequence Files

Hadoop中有些原生压缩文件的缺点之一就是不支持分割。支持分割的文件可以并行的有多个mapper程序处理大数据文件,大多数文件不支持可分割是因为这些文件只能从头开始读。Sequence File是可分割的文件格式,支持Hadoop的block级压缩。 Hadoop API提供的一种二进制文件,以key-value的形式序列化到文件中。存储方式:行存储。 sequencefile支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,RECORD是默认选项,通常BLOCK会带来较RECORD更好的压缩性能。 优势是文件和hadoop api中的MapFile是相互兼容的

3. RCFile

存储方式:数据按行分块,每块按列存储。结合了行存储和列存储的优点:

首先,RCFile 保证同一行的数据位于同一节点,因此元组重构的开销很低 其次,像列存储一样,RCFile 能够利用列维度的数据压缩,并且能跳过不必要的列读取 数据追加:RCFile不支持任意方式的数据写操作,仅提供一种追加接口,这是因为底层的 HDFS当前仅仅支持数据追加写文件尾部。 行组大小:行组变大有助于提高数据压缩的效率,但是可能会损害数据的读取性能,因为这样增加了 Lazy 解压性能的消耗。而且行组变大会占用更多的内存,这会影响并发执行的其他MR作业。

4.ORCFile

存储方式:数据按行分块,每块按照列存储。
压缩快,快速列存取。效率比rcfile高,是rcfile的改良版本。

5.Parquet

Parquet也是一种行式存储,同时具有很好的压缩性能;同时可以减少大量的表扫描和反序列化的时间

mapreduce可以选择压缩的地方:map阶段的输出和reduce阶段的输出。

--map阶段输出数据压缩 ,在这个阶段,优先选择一个低CPU开销的算法。

set hive.exec.compress.intermediate=true
set mapred.map.output.compression.codec= org.apache.hadoop.io.compress.SnappyCodec
set mapred.map.output.compression.codec=com.hadoop.compression.lzo.LzoCodec;


--用户可以对最终生成的Hive表的数据通常也需要压缩。
set hive.exec.compress.output=true 
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec

--一般选择orcfile/parquet + snappy 的方式

create table tablename (
 xxx,string
 xxx, bigint
)
ROW FORMAT DELTMITED FIELDS TERMINATED BY '\t'
STORED AS orc tblproperties("orc.compress" = "SNAPPY")


2、创建分区表,分桶表

创建分区表:(分区表相当于hive的索引,加快查询速度)

是指按照数据表的某列或某些列分为多个区,从形式上可以理解为分为多个文件夹

CREATE external TABLE table_name    
(col1 string,  col2 double) 
partitioned by (date string)  
 ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' ;
 
alter table table_name add partitions(key = 字段) location 'xxxx' (收到设置分区,静态分区)

通过调参设置动态分区

set hive.exec.dynamic.partition=true; --开启动态分区
set hive.exec.dynamic.partition.mode=nonstrict; (它的默认值是strick,即不允许分区列全部是动态的
SET hive.exec.max.dynamic.partitions=100000;--如果自动分区数大于这个参数,将会报错
SET hive.exec.max.dynamic.partitions.pernode=100000;--设置最大分区数

创建桶表:

分桶是相对分区进行更细粒度的划分。分桶将整个数据内容安装某列属性值得hash值进行区分,如要安装name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。

把表(或者分区)组织成桶(Bucket)有两个理由:

(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

(2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。

创建分桶表

create table bucketed_user(id int,name string) 
clustered by (id)
sorted by(name) 
into 4 buckets 
row format delimited fields terminated by '\t';

--再对分桶表中load数据时,要设置一个参数,以强制hive的reducer数目为分桶数。
--如果不设置这个hive参数,最后的桶个数可能不是建表语句中的个数
Set hive.enforce.bucketing=true;

3、hive参数优化

--开启任务并行执行
 set hive.exec.parallel=true;
--同一个sql允许并行任务的最大线程数 
set hive.exec.parallel.thread.number=8;

--JVM重用对hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景 
--大多数执行时间都很短。jvm的启动过程可能会造成相当大的开销,尤其是执行的job包含有多个tas任务的情况
set mapred.job.reuse.jvm.num.tasks=10; 

--设置reduce的数目
reduce个数的设定极大影响任务执行效率,不指定reduce个数的情况下,Hive会猜测确定一个reduce个数,基于以下两个设定: hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,在Hive 0.14.0版本之前默认值是1G(1,000,000,000);而从Hive 0.14.0开始,默认值变成了256M(256,000,000) ) hive.exec.reducers.max(每个任务最大的reduce数,在Hive 0.14.0版本之前默认值是999;而从Hive 0.14.0开始,默认值变成了1009 ) 计算reducer数的公式很简单N=min(参数2,总输入数据量/参数1) 即,如果reduce的输入(map的输出)总大小不超过1G,那么只会有一个reduce任务;
--调整reduce个数方法一: 调整hive.exec.reducers.bytes.per.reducer参数的值;
set hive.exec.reducers.bytes.per.reducer=500000000; (500M)
--调整reduce个数方法二;
set mapred.reduce.tasks = number
--reduce个数并不是越多越好; 同map一样,启动和初始化reduce也会消耗时间和资源; 另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题 

--推测执行
所谓的推测执行,就是当所有task都开始运行之后,Job Tracker会统计所有任务的平均进度,如果某个task所在的task node机器配置比较低或者CPU load很高(原因很多),导致任务执行比总体任务的平均执行要慢,此时Job Tracker会启动一个新的任务(duplicate task),原有任务和新任务哪个先执行完就把另外一个kill掉

4、优化sql

where条件优化(筛选要提前)
优化前(关系数据库不用考虑会自动优化):
select m.cid,u.id from order m join customer u on( m.cid =u.id )where m.dt='20180808';

优化后(where条件在map端执行而不是在reduce端执行):
select m.cid,u.id from (select * from order where dt='20180818') m join customer u on( m.cid =u.id);

union优化

尽量不要使用union (union 去掉重复的记录)而是使用 union all 然后在用group by 去重

count distinct优化

不要使用count (distinct   cloumn) ,使用子查询

select count(1) from (select id from tablename group by id) tmp;
 
用in 来代替join

如果需要根据一个表的字段来约束另为一个表,尽量用in来代替join .

select id,name from tb1  a join tb2 b on(a.id = b.id);
select id,name from tb1 where id in(select id from tb2); in 要比join 快
消灭子查询内的 group by 、 COUNT(DISTINCT),MAX,MIN。 可以减少job的数量。
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值