1.hive调优涉及到压缩和存储调优,参数调优,sql的调优,数据倾斜调优,小文件问题的调优等
2.数据的压缩与储存格式
2.1. 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;
2. 2. 对最终输出结果压缩
set hive.exec.compress.output=true
set mapred.output.compression.codec=org.apache.hadoop.io.compress.SnappyCodec
##当然,也可以在hive建表时指定表的文件格式和压缩编码
结论,一般选择orcfile/parquet + snappy 方式
3.建表时合理利用分区分桶
分区是将表的数据在物理上分成不同的文件夹,以便于在查询时可以精准指定所要读取的分区目录,从来降低读取的数据量
分桶是将表数据按指定列的hash散列后分在了不同的文件中,将来查询时,hive可以根据分桶结构,快速定位到一行数据所在的分桶文件,从来提高读取效率
分区表:原来的一个大表存储的时候分成不同的数据目录进行存储。如果说是单分区表,那么在表的目录下就只有一级子目录,如果说是多分区表,那么在表的目录下有多少分区就有多少级子目录。不管是单分区表,还是多分区表,在表的目录下,和非最终分区目录下是不能直接存储数据文件的
分桶表:原理和hashpartitioner 一样,将hive中的一张表的数据进行归纳分类的时候,归纳分类规则就是hashpartitioner。(需要指定分桶字段,指定分成多少桶)
分区表和分桶的区别除了存储的格式不同外,最主要的是作用:
分区表:细化数据管理,缩小mapreduce程序 需要扫描的数据量。
分桶表:提高join查询的效率,在一份数据会被经常用来做连接查询的时候建立分桶,分桶字段就是连接字段;提高采样的效率。
有了分区为什么还要分桶?
(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive在处理有些查询时能利用这个结构。
(2)使取样( sampling)更高效。在处理大规模数据集时,在开发和修改査询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
分桶是相对分区进行更细粒度的划分。分桶将表或者分区的某列值进行hash值进行区分,如要按照name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。
与分区不同的是,分区依据的不是真实数据表文件中的列,而是我们指定的伪列,但是分桶是依据数据表中真实的列而不是伪列
4.hive参数优化
4.1// 让可以不走mapreduce任务的,就不走mapreduce任务
hive> set hive.fetch.task.conversion=more;
4.2// 开启任务并行执行
set hive.exec.parallel=true;
// 解释:当一个sql中有多个job时候,且这多个job之间没有依赖,则可以让顺序执行变为并行执行(一般为用到union all的时候)
4.3 // 同一个sql允许并行任务的最大线程数
set hive.exec.parallel.thread.number=8;
4.4// 设置jvm重用
// JVM重用对hive的性能具有非常大的 影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。jvm的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况。
set mapred.job.reuse.jvm.num.tasks=10;
4.5// 合理设置reduce的数目
// 方法1:调整每个reduce所接受的数据量大小
set hive.exec.reducers.bytes.per.reducer=500000000; (500M)
4.6// 方法2:直接设置reduce数量
set mapred.reduce.tasks = 20
4.7// map端聚合,降低传给reduce的数据量
set hive.map.aggr=true
4.8// 开启hive内置的数倾优化机制(负载均衡)
set hive.groupby.skewindata=true
5.sql优化
5.1 对于这个调优,有待再次验证目前我验证了4千万 join 8千万发现不管是left join还是inner join,执行计划差不多,job数,maptask,reducetask数都一样,执行时长也差不多可能都已经自动优化了(谓词下推)
select
count(1)
from test1 t1
inner join test2 t2
on t1.uuid = t2.uuid and t2.date_id = ‘2020-10-23’
where t1.date_id = ‘2020-10-23’;
select
count(1)
from (select * from test1 where date_id = ‘2020-10-23’) t1
inner join test2 t2
on t1.uuid = t2.uuid and t2.date_id = ‘2020-10-23’
;</