关于hive的优化
Hive倾斜—不患寡而患不均
一、创建表时候的优化
a) 大表拆分为小表
b) 如果使用外部分区表的话,要注意多级分区,比如以天为分区的话,每天为分区,以小时为分区的话,要以小时为二级分区。
c) 数据存储:更改存储格式、数据压缩。
二、对表数据查询的优化
a) Sql语句的优化:尽可能的加入合理的过滤语句,使查询到的数据更合理、更少而有效;对于分区表的查询尽可能使用分区字段。
b) 对MapReduce的优化:对reduce个数的优化、对jvm重用、数据查询之前的推测执行等。
c) 具体如下
三、一些小技巧
1、对fetch task的优化
我们可以使用fetch taske更改显示内容的多少。
设置参数的优先级:在命令行或者代码设置参数 > hive-site.xml>hive-default.xml
或者:set hive.fetch.task.conversion=more; //单次交互模式下有效,
或者以这种模式运行hive:bin/hive --hiveconf hive.fetch.task.conversion=more
2、开启严格模式
strictmode:严格模式设置,严格模式下将会限制一些查询操作
文件格式,ORC PARQUET 等
分区表
select 查询不加where过滤条件,不会执行
四、查询操作优化
优化sql语句,如先过滤再join;先分组(group by)再做distinct;
1、加入分组
原因:如果有1TB的数据,如果单次查询,可能会只是用一个reduce,但是如果我们加入了分组(group by),就会调用多个reduce,这使效率提高。
eg1.
Select count(*)cnt
From store_salesss
join household_demographics hd on(ss.ss_hdemo_sk = hd.hd_demo_sk)
join time_dim t on (ss.ss_sold_time_sk =t.t_time_sk)
join store s on (s.s_store_sk =ss.ss_store_sk)
Where
t.t_hour = 8
t.t_minute >= 30
hd.hd_dep_count = 2
order by cnt;
2、全表关联的时候join的同时过滤
在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤,比如:
SELECT a.empno
FROM emp a
left outer joinemp_part b
ON (a.deptno =b.depno)
WHERE b.day ='20150828′;
正确的写法是写在ON后面:
SELECT a.id
FROM emp a
left outer joinemp_part b
ON (a.deptno = b.depno AND b.day = '2015082818');
3、先分组,在DISTINCT
少用COUNT DISTINCT
数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换:
eg3.
SELECT day,
COUNT(DISTINCTid) AS uv
FROM emp
GROUP BY day
可以转换成:
SELECT day,
COUNT(id) AS uv
FROM (SELECTday,id FROM emp GROUP BY day,id) a
GROUP BY day;
4. MapReduce过程的map、shuffle、reduce端的snappy压缩
需要先替换hadoop的native本地包开启压缩
在mapred-site.xml文件设置启用压缩及压缩编码
在执行SQL执行时设置启用压缩和指定压缩编码
5、设置Map和reduce个数:默认情况下一个块对应一个map任务,map数据我们一般不去调整,
reduce个数根据reduce处理的数据量大小进行适当调整
这体现了“分而治之”的思想。
确定map个数与合并小文件。
6、hive的并行执行
假设一个sql语句运行的时候产生多个job,比如一个sql与1.2.3个job,其中第1、2个job在查询(join查询语句)的过程后在与第三个job结果进行join查询,我们可以将1、2job在join同时job3可以同时并行执行。
分布式并行化
set hive.exec.parallel=true; //一次性配置
set hive.exec.parallel.thread.number=8;
7、JVM重用
一个job可能有多个map reduce任务,每个任务会开启一个JVM虚拟机,默认情况下一个任务对应一个JVM,任务运行完JVM即销毁,到了下一次MapReduce任务又会重启。这样大大消耗了时间。
因此我们可以设置JVM重用参数,一般不超过5个,这样一个JVM内可以连续运行多个任务,jvm不会销毁。
JVM重用是Hadoop调优参数的内容,对Hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。hadoop默认配置是使用派生JVM来执行map和reduce任务的,这是jvm的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况。
JVM重用可以使得JVM实例在同一个JOB中重新使用N次,N的值可以在Hadoop的mapre-site.xml文件中进行设置(建议参考5~10)
mapred.job.reuse.jvm.num.tasks(旧版)
mapreduce.job.jvm.numtasks(新版)
hadoop.apache.org/docs/r2.5.2/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
http://hadoop.apache.org/docs/r2.5.2/hadoop-mapreduce-client/hadoop-mapreduce-client-core/mapred-default.xml
8、推测执行:例如一个Job应用有10个MapReduce任务(map 及reduce),其中9个任务已经完成,那么application Master会在另外启动一个相同的任务来运行未完成的那个,最后哪个先运行完成就把另一个kill掉
启用speculative最大的好处是,一个map执行的时候,系统会在其他空闲的服务器上启动相同的map来同时运行,哪个运行的快就使用哪个的结果,另一个运行慢的在有了结果之后就会被kill。