Hive 优化
Hive中跑MapReduce Job出现OOM问题分析及解决
https://blog.csdn.net/oopsoom/article/details/41356251
======================================================================================================================================================================================================
hive优化1
======================================================================================================================================================================================================
1.聚合优化
set hive.map.aggr=true;
处罚map阶段顶级聚合过程,这个设置需要更多的内存。
2.本地模式
set hive.exec.mode.local.auto=true;
hive会尝试用本地模式执行操作
3.join优化
a.少MapReduce
select a.ymd,a.price_close,b.price_close,c.price_close
from stocks a
join stocks b on a.ymd=b.ymd
join stocks c on a.ymd=c.ymd
where a.symbol = 'AAPL' and b.symbol = 'IBM' and c.symbol = 'GE';
on 后面都有相同的a.ymd 可以放一个mapreduce ,在一个mapreduce中连接三张表。
b.小表放前面,大表放后面。
hive会假定最后一个表是最大的表,将前面的表缓存起来。
当然,也可以智能指定,如:
select /*+STREAMTABLE(s) */ s.ymd,s.symbol,s.price_close,d.dividend
from stock s join dividends d on s.ymd=d.ymd and s.symbol=d.symbol where s.symbol='appl' ;
4.LEFT OUTER JOIN优化
左连接时,左表中出现的JOIN字段都保留,右表没有连接上的都为空。对于带WHERE条件的JOIN语句,例如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON(a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
执行顺序是,首先完成2表JOIN,然后再通过WHERE条件进行过滤,这样在JOIN过程中可能会输出大量结果,再对这些结果进行过滤,比较耗时。可以进行优化,将WHERE条件放在ON后,例如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON(a.key=b.key AND b.ds='2009-07-07'AND a.ds='2009-07-07')
这样,在JOIN的过程中,就对不满足条件的记录进行了预先过滤,可能会有更好的表现。
5.Map Side JOIN
Map Side JOIN优化的出发点是,Map任务输出后,不需要将数据拷贝到Reducer节点,降低的数据在网络节点之间传输的开销。
多表连接,如果只有一个表比较大,其他表都很小,则JOIN操作会转换成一个只包含Map的Job,例如:
SELECT /*+ MAPJOIN(b) */ a.key, a.value FROM a JOIN b ON a.key = b.key
对于表a数据的每一个Map,都能够完全读取表b的数据。这里,表a与b不允许执行FULL OUTER JOIN、RIGHT OUTER JOIN。
6.并行执行
hive的查询会转变成一个或者多个阶段,这样的阶段可以是mapreduce阶段,抽样阶段,合并阶段,limit阶段
或者是hive执行中可能需要的其他阶段。默认情况下,hive只会执行一个阶段,不过某些特定的job会执行多个阶段,而这些阶段有些事没有互相依赖的,这些没有依赖的是可以并行执行的,缩短时间。
开发并发执行 set hive.exec.parallel=true;
7.jvm重用
?JVM重用是是hadoop调优参数的内容,其对hadoop的性能有非常大的影响,特别对于很难避免小文件的场景或者是task特别多的场景,这类场景大多数执行时间很短,hadoop默认配置通常是使用派生JVM来执行map和reduce任务的,这是jvm启动可能造成很大的开销,尤其是执行的job包含成百上千task任务的情况。JVM重用可以使得JVM实例在同一个job中重新使用了N次。
参数设置 set mapred.job.reuse.jvm.num.tasks=10;
缺点;
开启jvm将会一直占用使用的task插槽,以便进行重用,知道任务完成后才能释放。如果某个不平衡的job中有几个reduce task要比其他的reduce task消耗的时间多的多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。
======================================================================================================================================================================================================
hive优化2
======================================================================================================================================================================================================
1.脚本参数设置
1.1 简单列查询不启用mapreduce
set hive.fetch.task.conversion=more;
开启了Fetch任务,所以对于简单的列查询不在启用MapReduce job!
例如:SELECT id, money FROM m limit 10;
1.2 是否显示表的列名
set hive.cli.print.header=true;
是否显示表的列名。
例如:
hive> set hive.cli.print.header=true;
hive> select * from t04;
OK
id name
Time taken: 0.136 seconds
hive> set hive.cli.print.header=false;
hive> select * from t04;
OK
Time taken: 0.08 seconds
1.3 设置最大rudece个数
set hive.exec.reducers.max=88;
最大的reduce的个数为88.
1.4 hive输出是否进行压缩
set hive.exec.compress.output=false;
最终结果不压缩
set hive.exec.compress.intermediate=true;
中间结果压缩,决定查询的中间 map/reduce job (中间 stage)的输出是否为压缩格式。
1.5 合并小文件
Set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
在执行之前进行小文件合并
set mapred.max.split.size=256000000;
合并文件最大为256M
set mapred.min.split.size.per.node=1;(设置大小不合理)
set mapred.min.split.size.per.rack=1;(设置大小不合理)
例如:
set mapred.max.split.size=1000;
set mapred.min.split.size.per.node=300;
set mapred.min.split.size.per.rack=100;
输入目录下五个文件,rack1下三个文件,长度为2050,1499,10, rack2下两个文件,长度为1010,80. 另外blockSize为500.
经过第一步, 生成五个split: 1000,1000,1000,499,1000. 剩下的碎片为rack1下:50,10; rack2下10:80
由于两个rack下的碎片和都不超过100, 所以经过第二步, split和碎片都没有变化.
第三步,合并四个碎片成一个split, 长度为150.
1.6 MapJoin机制
set hive.ignore.mapjoin.hint=true;
set hive.auto.convert.join = true;
set hive.smalltable.filesize=1000000000;(设置大小不合理)
开启mapjoin优化机制
1.7队列job名
set mapred.queue.name=oia;
set mapred.job.queue.name=oia;
Set mapred.job.name=oia_${pt_month}_${v_proc_name};
2.其他参数
2.1 本地模式
set hive.exec.mode.local.auto=true;
Hive会自动选择是否用本地模式
0.7版本后Hive开始支持任务执行选择本地模式(local mode)。大多数的Hadoop job是需要hadoop提供的完整的可扩展性来处理大数据的。不过,有时hive的输入数据量是非常小的。在这种情况下,为查询出发执行任务的时间消耗可能会比实际job的执行时间要多的多。对于大多数这种情况,hive可以通过本地模式在单台机器上处理所有的任务。对于小数据集,执行时间会明显被缩短。
如此一来,对数据量比较小的操作,就可以在本地执行,这样要比提交任务到集群执行效率要快很多。
2.2 数据倾斜
Set hive.groupby.skewindata = true;
有数据倾斜的时候进行负载均衡
2.3 并行执行
hive的查询会转变成一个或者多个阶段,这样的阶段可以是mapreduce阶段,抽样阶段,合并阶段,limit阶段
或者是hive执行中可能需要的其他阶段。默认情况下,hive只会执行一个阶段,不过某些特定的job会执行多个阶段,而这些阶段有些事没有互相依赖的,这些没有依赖的是可以并行执行的,缩短时间。
开发并发执行 set hive.exec.parallel=true;
2.4 jvm重用
?JVM重用是是hadoop调优参数的内容,其对hadoop的性能有非常大的影响,特别对于很难避免小文件的场景或者是task特别多的场景,这类场景大多数执行时间很短,hadoop默认配置通常是使用派生JVM来执行map和reduce任务的,这是jvm启动可能造成很大的开销,尤其是执行的job包含成百上千task任务的情况。JVM重用可以使得JVM实例在同一个job中重新使用了N次。
参数设置 set mapred.job.reuse.jvm.num.tasks=10;
缺点:
开启jvm将会一直占用使用的task插槽,以便进行重用,知道任务完成后才能释放。如果某个不平衡的job中有几个reduce task要比其他的reduce task消耗的时间多的多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。
3.join优化
3.1 执行计划
EXPLAIN SELECT SUM(Number) FROM onecol
可以看一个sql的执行计划,怎么样解析执行的情况。
3.2 表顺序
小表放前面,大表放后面,hive会假定后面的一张表是大表,将前面的缓存起来。
3.3 LEFT OUTER JOIN优化
左连接时,左表中出现的JOIN字段都保留,右表没有连接上的都为空。对于带WHERE条件的JOIN语句,例如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b ON(a.key=b.key)
WHERE a.ds='2009-07-07' AND b.ds='2009-07-07'
执行顺序是,首先完成2表JOIN,然后再通过WHERE条件进行过滤,这样在JOIN过程中可能会输出大量结果,再对这些结果进行过滤,比较耗时。可以进行优化,将WHERE条件放在ON后,例如:
SELECT a.val, b.val FROM a LEFT OUTER JOIN b
ON(a.key=b.key AND b.ds='2009-07-07'AND a.ds='2009-07-07')
这样,在JOIN的过程中,就对不满足条件的记录进行了预先过滤,可能会有更好的表现。
======================================================================================================================================================================================================
常用优化参数
======================================================================================================================================================================================================
set hive.fetch.task.conversion=more;
set hive.cli.print.header=true;
set hive.exec.reducers.max=88;
set hive.exec.compress.output=false;
set hive.exec.compress.intermediate=true;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set mapred.max.split.size=128000000;
set mapred.min.split.size.per.node=128000000;
set mapred.min.split.size.per.rack=128000000;
set hive.ignore.mapjoin.hint=true;
set hive.auto.convert.join = true;
set hive.smalltable.filesize=25000000;
--set mapred.queue.name=oia;
--set mapred.job.queue.name=oia;
--set mapred.job.name=oia_${pt_month}_${v_proc_name};
set hive.exec.mode.local.auto=true;
set hive.groupby.skewindata = true;
set hive.exec.parallel=true;
set mapred.job.reuse.jvm.num.tasks=10;
set hive.fetch.task.conversion=more;
set hive.cli.print.header=true;
set hive.exec.reducers.max=88;
set hive.exec.compress.output=false;
set hive.exec.compress.intermediate=true;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set mapred.max.split.size=128000000;
set mapred.min.split.size.per.node=128000000;
set mapred.min.split.size.per.rack=128000000;
set hive.ignore.mapjoin.hint=true;
set hive.auto.convert.join = true;
set hive.smalltable.filesize=25000000;
set hive.exec.mode.local.auto=true;
set hive.groupby.skewindata = true;
set hive.exec.parallel=true;
set mapred.job.reuse.jvm.num.tasks=10;
hive统计parquet表报错
https://blog.csdn.net/lhxsir/article/details/83789102
parquet列式存储格式,所以优先统计某一列:
SELECT count(salesorder_id) FROM tt_sales_order;