Hive-05 参数调优
调优
Hive提供三种可以改变环境变量的方法,分别是:
(1)修改${HIVE_HOME}/conf/hive-site.xml配置文件;
所有的默认配置都在${HIVE_HOME}/conf/hive-default.xml文件中,如果需要对默认的配置进行修改,可以创建一个hive-site.xml文件,放在${HIVE_HOME}/conf目录下。里面可以对一些配置进行个性化设定。这里做的配置都全局用户都生效,而且是永久的。
(2)命令行参数;
在启动Hive cli的时候进行配置,可以在命令行添加-hiveconf param=value来设定参数;这一设定对本次启动的会话有效,下次启动需要重新配置。
(3)在已经进入cli时进行参数声明。
可以在HQL中使用SET关键字设定参数,这种配置也是对本次启动的会话有效,下次启动需要重新配置。在HQL中使用SET关键字还可以查看配置的值。
set后面什么都不添加,这样可以查到Hive的所有属性配置。
上述三种设定方式的优先级依次递增。即参数声明覆盖命令行参数,命令行参数覆盖配置文件设定。
服务器和客户端中都要进行配置;
https://www.cnblogs.com/ITtangtang/p/7683028.html
1. 执行计划(Explain)
1)基本语法
EXPLAIN [EXTENDED | DEPENDENCY | AUTHORIZATION] query
2)案例实操
(1)查看下面这条语句的执行计划
没有生成MR任务的
hive (default)> explain select * from emp;
Fetch Operator
Explain STAGE DEPENDENCIES: Stage-0 is a root stage STAGE PLANS: Stage: Stage-0 Fetch Operator limit: -1 Processor Tree: TableScan alias: emp Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE Select Operator expressions: empno (type: int), ename (type: string), job (type: string), mgr (type: int), hiredate (type: string), sal (type: double), comm (type: double), deptno (type: int) outputColumnNames: _col0, _col1, _col2, _col3, _col4, _col5, _col6, _col7 Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE ListSink
有生成MR任务的
hive (default)> explain select deptno, avg(sal) avg_sal from emp group by deptno;
Map Operator Tree:
Reduce Operator Tree:
Select Operator
File Output Operator
Fetch Operator
Explain STAGE DEPENDENCIES: Stage-1 is a root stage Stage-0 depends on stages: Stage-1 STAGE PLANS: Stage: Stage-1 Map Reduce Map Operator Tree: TableScan alias: emp Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE Select Operator expressions: sal (type: double), deptno (type: int) outputColumnNames: sal, deptno Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE Group By Operator aggregations: sum(sal), count(sal) keys: deptno (type: int) mode: hash outputColumnNames: _col0, _col1, _col2 Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE Reduce Output Operator key expressions: _col0 (type: int) sort order: + Map-reduce partition columns: _col0 (type: int) Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE value expressions: _col1 (type: double), _col2 (type: bigint) Execution mode: vectorized Reduce Operator Tree: Group By Operator aggregations: sum(VALUE._col0), count(VALUE._col1) keys: KEY._col0 (type: int) mode: mergepartial outputColumnNames: _col0, _col1, _col2 Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE Select Operator expressions: _col0 (type: int), (_col1 / _col2) (type: double) outputColumnNames: _col0, _col1 Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE File Output Operator compressed: false Statistics: Num rows: 1 Data size: 7020 Basic stats: COMPLETE Column stats: NONE table: input format: org.apache.hadoop.mapred.SequenceFileInputFormat output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe Stage: Stage-0 Fetch Operator limit: -1 Processor Tree: ListSink
(2)查看详细执行计划
hive (default)> explain extended select * from emp;
hive (default)> explain extended select deptno, avg(sal) avg_sal from emp group by deptno;
2. Fetch抓取
Fetch抓取是指,Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文
件,然后输出查询结果到控制台。
在hive-default.xml文件中
hive.fetch.task.conversion默认是more,老版本hive默认是minimal,该属性修改为more以后,在全局查找、字段查找、limit查找等都不走mapreduce。
set hive.fetch.task.conversion.threshold=1073741824,可调整阈值,默认1G,小于1G才会使用Fatch抓取模式;
Fetch抓取
set hive.fetch.task.conversion=none;
把hive.fetch.task.conversion设置成none,然后执行查询语句,都会执行mapreduce程序。
select * from emp; // number of mappers: 1; number of reducers: 0
set hive.fetch.task.conversion=more;
把hive.fetch.task.conversion设置成more,然后执行查询语句,如下查询方式都不会执行mapreduce程序。
select * from emp;
3. 本地模式
大多数的Hadoop Job是需要Hadoop提供的完整的可扩展性来处理大数据集的。不过,
有时Hive的输入数据量是非常小的。在这种情况下,为查询触发执行任务消耗的时间可能会比实际job的执行时间要多的多。对于大多数这种情况,Hive可以通过本地模式在单台机器
上处理所有的任务。对于小数据集,执行时间可以明显被缩短。
可通过设置hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化,默认是false。
set hive.exec.mode.local.auto=true; //开启本地mr
set hive.exec.mode.local.auto.inputbytes.max=50000000; //设置local mr的最大输入数据量,当输入数据量小于这个值时采用local, mr的方式,默认为134217728,即128M
set hive.exec.mode.local.auto.input.files.max=10; //设置local mr的最大输入文件个数,当输入文件个数小于这个值时采用local, mr的方式,默认为4
当一个job满足如下条件才能真正使用本地模式:
1.job的输入数据大小必须小于参数:hive.exec.mode.local.auto.inputbytes.max(默认128MB)
2.job的map数必须小于参数:hive.exec.mode.local.auto.tasks.max(默认4)
3.job的reduce数必须为0或者1
可用参数hive.mapred.local.mem(默认0)控制child jvm使用的最大内存数。
4. 并行执行
Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。
默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整
个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成。
通过设置参数hive.exec.parallel值为true,就可以开启并发执行。不过,在共享集群中,需要注意下,如果job中并行阶段增多,那么集群利用率就会增加。
set hive.exec.parallel=true; //打开任务并行执行
set hive.exec.parallel.thread.number=16; //同一个sql允许最大并行度,默认为8。
当然,得是在系统资源比较空闲的时候才有优势,否则,没资源,并行也起不来。
5. 合理设置Map及Reduce数
Reduce的个数对整个作业的运行性能有很大影响。如果Reduce设置的过大,那么将会产生很多小文件,对NameNode会产生一定的影响,而且整个作业的运行时间未必会减少;如果
Reduce设置的过小,那么单个Reduce处理的数据将会加大,很可能会引起OOM异常。
1)通常情况下,作业会通过input的目录产生一个或者多个map任务。
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
2)是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑
处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
3)是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去
做,肯定也比较耗时。针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;
5.1 复杂文件增加Map数
当input的文件都很大,任务逻辑复杂,map执行非常慢的时候,可以考虑增加Map数,来使得每个map处理的数据量减少,从而提高任务的执行效率。
增加map的方法为:根据computeSliteSize(Math.max(minSize,Math.min(maxSize,blocksize)))=blocksize=128M公式,调整maxSize最大值。让maxSize最大值低于blocksize就可以增
加map的个数。
1.执行查询
hive (default)> select count(*) from emp;
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
2.设置最大切片值为100个字节
hive (default)> set mapreduce.input.fileinputformat.split.maxsize=100;
hive (default)> select count(*) from emp;
Hadoop job information for Stage-1: number of mappers: 6; number of reducers: 1
5.2 小文件进行合并
配置Map输入合并 -- 每个Map最大输入大小,决定合并后的文件数 set mapred.max.split.size=256000000;
-- 一个节点上split的至少的大小 ,决定了多个data node上的文件是否需要合并 set mapred.min.split.size.per.node=100000000;
-- 一个交换机下split的至少的大小,决定了多个交换机上的文件是否需要合并 set mapred.min.split.size.per.rack=100000000;
-- 执行Map前进行小文件合并; 在map执行前合并小文件,减少map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。
-- HiveInputFormat没有对小文件合并功能。 set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; 配置在Map-Reduce任务结束时合并小文件 我们可以通过一些配置项来使Hive在执行结束后对结果文件进行合并: set hive.merge.mapfiles=true //在map-only job后合并文件,默认true,在map-only任务结束时合并小文件
set hive.merge.mapredfiles=true //在map-reduce job后合并文件,默认false,设为true 在map-reduce任务结束时合并小文件
set hive.merge.size.per.task=true //合并后每个文件的大小,默认268435456,合并文件的大小,默认256M
set hive.merge.smallfiles.avgsize=true //平均文件大小,是决定是否执行合并操作的阈值,默认16777216,当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge Hive在对结果文件进行合并时会执行一个额外的map-only脚本,mapper的数量是文件总大小除以size.per.task参数所得的值,触发合并的条件是: 根据查询类型不同,相应的mapfiles/mapredfiles参数需要打开; 结果文件的平均大小需要大于avgsize参数的值。
5.3 合理设置Reduce数
1.调整reduce个数方法一
(1)每个Reduce处理的数据量默认是256MB
hive.exec.reducers.bytes.per.reducer=256000000
(2)每个任务最大的reduce数,默认为1009
hive.exec.reducers.max=1009
(3)计算reducer数的公式
N=min(参数2,总输入数据量 / 参数1)
2.调整reduce个数方法二
在hadoop的mapred-default.xml文件中修改
设置每个job的Reduce个数
set mapreduce.job.reduces = 15;
3.reduce个数并不是越多越好
1)过多的启动和初始化reduce也会消耗时间和资源;
2)另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适;
reduce数量由以下三个参数决定:
- mapred.reduce.tasks ( 强制指定reduce的任务数量,默认为-1 )
- hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为256000000)
- hive.exec.reducers.max(每个任务最大的reduce数,默认为1009)
计算reducer数的公式很简单 N = min ( hive.exec.reducers.max ,总输入数据量/ hive.exec.reducers.bytes.per.reducer )
6. 表的优化
6.1 小表join 大表 MapJoin
将key相对分散,并且数据量小的表放在join的左边,可以使用map join让小的维度表先进内存。在map端完成join。
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加
载到内存在map端进行join,避免reducer处理。
1.开启MapJoin参数设置
(1)设置自动选择Mapjoin
set hive.auto.convert.join = true; // 默认为true
(2)大表小表的阈值设置(默认25M一下认为是小表):
set hive.mapjoin.smalltable.filesize=25000000;
将key相对分散,并且数据量小的表放在join的左边,这样可以有效减少内存溢出错误发生的几率;再进一步,可以使用map join让小的维度表(1000条以下的记录条数)先进内存。
在map端完成reduce。
实际测试发现:新版的hive已经对小表JOIN大表和大表JOIN小表进行了优化。小表放在左边和右边已经没有明显区别。
Hive0.11之后 set hive.auto.convert.join=true 默认是true,即开启了map join的优化;
hive.mapjoin.smalltable.filesize=25000000 通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值(25M)就会被加载进内存中
创建大表、小表、join后的表、加载数据、 hive (default)> create table bigtable( > id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) > row format delimited fields terminated by '\t'; OK Time taken: 0.103 seconds hive (default)> create table smalltable( > id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) > row format delimited fields terminated by '\t'; OK Time taken: 0.109 seconds hive (default)> create table jointable( > id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) > row format delimited fields terminated by '\t'; OK Time taken: 0.486 seconds hive (default)> load data local inpath '/opt/module/datas/bigtable' into table bigtable; Loading data to table default.bigtable Table default.bigtable stats: [numFiles=1, totalSize=120734753] OK Time taken: 1.26 seconds hive (default)> load data local inpath '/opt/module/datas/smalltable' into table smalltable; Loading data to table default.smalltable Table default.smalltable stats: [numFiles=1, totalSize=12018355] OK Time taken: 3.736 seconds hive (default)> set hive.auto.convert.join=false; 关闭mapjoin功能(默认是打开的) 小表join大表 hive (default)> insert overwrite table jointable select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url from smalltable s left join bigtable b on s.id=b.id; Time taken: 40.392 seconds 大表join小表 hive (default)> insert overwrite table jointable select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url from bigtable b left join smalltable s on b.id=s.id; Time taken: 39.82 seconds
6.2 大表Join大表
1.空KEY过滤
有时join超时是因为某些key对应的数据太多,而相同key对应的数据都会发送到相同的reducer上,从而导致内存不够。此时我们应该仔细分析这些异常的key,很多情况下,这些key
对应的数据是异常数据,我们需要在SQL语句中进行过滤。例如key对应的字段为空,操作如下:
案例实操
1)配置历史服务器
配置mapred-site.xml
<property> <name>mapreduce.jobhistory.address</name> <value>hadoop101:10020</value> </property> <property> <name>mapreduce.jobhistory.webapp.address</name> <value>hadoop101:19888</value> </property>
启动历史服务器
sbin/mr-jobhistory-daemon.sh start historyserver
查看jobhistory http://hadoop103:19888/jobhistory
测试过滤主键为null的数据的效果
创建原始表、创建空id表、创建join后的表、分别加载数据 hive (default)> create table ori(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) > row format delimited fields terminated by '\t'; OK Time taken: 0.129 seconds hive (default)> create table nullidtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) > row format delimited fields terminated by '\'; OK hive (default)> load data local inpath '/opt/module/datas/nullid' into table nullidtable; //加载数据 测试不过滤空id hive (default)> insert overwrite table jointable select n.* from nullidtable n left join ori o on o.id=n.id; Time taken: 52.863 seconds 测试过滤空id hive (default)> insert overwrite table jointable select n.* from (select * from nullidtable where id is not null) n left join ori o on n.id=o.id; Time taken: 30.157 seconds
2.空key转换
有时虽然某个key为空对应的数据很多,但是相应的数据不是异常数据,必须要包含在join的结果中,此时我们可以表a中key为空的字段赋一个随机的值,使得数据随机均匀地分不到
不同的reducer上。
set mapreduce.job.reduces=-1 默认是-1,Hive会根据输入文件的大小估算出Reduce的个数。根据输入文件估算Reduce的个数可能未必很准确,因为Reduce的输入是Map的输出,
而Map的输出可能会比输入要小,所以最准确的数根据Map的输出估算Reduce的个数。
不随机分布空null值:
set mapreduce.job.reduces=5;
insert overwrite table jointable select n.* from nullidtable n left join ori o on o.id=n.id;
Time taken: 38.521 seconds
结果可以看出来,出现了数据倾斜,某些reducer的资源消耗远大于其他reducer。
随机分布空null值
insert overwrite table jointable
select n.* from nullidtable n
full join ori o
on case when n.id is null then concat('hive', rand()) else n.id end = o.id;
Time taken: 55.743 seconds
结果可以看出来,消除了数据倾斜,负载均衡reducer的资源消耗
3. SMB(Sort Merge Bucket join)
1)创建第二张大表 bigtable2
create table bigtable2( id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t'; load data local inpath '/opt/module/datas/bigtable' into table bigtable2;
测试大表直接JOIN
insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable s
join bigtable2 b
on b.id = s.id;
2)创建分通表bigtable_buck1, 桶的个数不要超过可用CPU的核数
create table bigtable_buck1( id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) clustered by(id) sorted by(id) into 6 buckets row format delimited fields terminated by '\t'; load data local inpath '/opt/module/data/bigtable' into table bigtable_buck1;
3)创建分通表bigtable_buck2, 桶的个数不要超过可用CPU的核数
create table bigtable_buck2( id bigint, t bigint, uid string, keyword string, url_rank int, click_num int, click_url string) clustered by(id) sorted by(id) into 6 buckets row format delimited fields terminated by '\t'; load data local inpath '/opt/module/data/bigtable' into table bigtable_buck2;
4)设置参数| 测试
设置参数
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
测试
insert overwrite table jointable
select b.id, b.t, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable_buck1 s
join bigtable_buck2 b
on b.id = s.id;
6.3 Group By
默认情况下,Map阶段同一Key数据分发给一个reduce,当一个key数据过大时就倾斜了。
并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。
set hive.groupby.skewindata=true;
select deptno from emp group by deptno;
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
set hive.groupby.skewindata=true; 有数据倾斜的时候进行负载均衡(默认是false)
select deptno from emp group by deptno;
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
Hadoop job information for Stage-2: number of mappers: 1; number of reducers: 1
当选项设定为 true,生成的查询计划会有两个MR Job。
第一个MR Job中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By
Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;
第二个MR Job再根据预处理的数据结果按照Group By Key分布到Reduce中(这个过程可以保证相同的Group By Key被分布到同一个Reduce中),
最后完成最终的聚合操作。
6.4 Count(Distinct) 去重统计
数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT的全聚合操作,即使设定了reduce task个数,set mapred.reduce.tasks=100;
hive也只会启动一个reducer,这就造成一个Reduce处理的数据量太大,导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换:
set mapreduce.job.reduces=5; 设置5个reduce个数
set hive.groupby.skewindata=false;
去重id查询
select count(distinct id) from bigtable;
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1
GROUP by去重id
select count(id) from (select id from bigtable group by id) a;
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 5
Hadoop job information for Stage-2: number of mappers: 1; number of reducers: 1
虽然会多用一个Job来完成,但在数据量大的情况下,这个绝对是值得的。
6.5 笛卡尔积
尽量避免笛卡尔积,join的时候不加on条件,或者无效的on条件,Hive只能使用1个reducer来完成笛卡尔积。
6.6 行列过滤
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤,比如:
1.测试先关联两张表,再用where条件过滤
select o.id from bigtable b
join ori o on o.id = b.id
where o.id <= 10;
Time taken: 34.406 seconds, Fetched: 100 row(s)
2.通过子查询后,再关联表
select b.id from bigtable b
join (select id from ori where id <= 10 ) o on b.id = o.id;
Time taken: 30.058 seconds, Fetched: 100 row(s)
6.7 动态分区调整
关系型数据库中,对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中,Hive中也提供了类似的机制,即动态分区(Dynamic Partition),只不过,
使用Hive的动态分区,需要进行相应的配置。
开启动态分区参数设置
(1)开启动态分区功能(默认true,开启)
hive.exec.dynamic.partition=true
(2)设置为非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区。)
hive.exec.dynamic.partition.mode=nonstrict
(3)在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000
hive.exec.max.dynamic.partitions=1000
(4)在每个执行MR的节点上,最大可以创建多少个动态分区。该参数需要根据实际的数据来设定。
比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错。
hive.exec.max.dynamic.partitions.pernode=100
(5)整个MR Job中,最大可以创建多少个HDFS文件。默认100000
hive.exec.max.created.files=100000
(6)当有空分区生成时,是否抛出异常。一般不需要设置。默认false
hive.error.on.empty.partition=false
create table dept_partitions(id int, name string)
partitioned by (location int)
row format delimited fields terminated by '/t';
set hive.exec.dynamic.partition.mode=nonstrict; 设置动态分区
insert into table dept_partitions partition(location) select deptno, name, loc from dept;
insert into table dept_partitions partition(location) select deptno, dname, loc from dept;
show partitions dept_partitions; 查看目标分区表的分区情况
+----------------+--+
| partition |
+----------------+--+
| location=1700 |
| location=1800 |
| location=1900 |
+----------------+--+
rows selected (0.14 seconds)
6.8 分桶
6.9 分区
7. 严格模式
Hive提供了一个严格模式,可以防止用户执行那些可能意想不到的不好的影响的查询。
通过设置属性hive.mapred.mode值为默认是非严格模式nonstrict 。开启严格模式需要修改hive.mapred.mode值为strict,开启严格模式可以禁止3种类型的查询。
1)对于分区表,除非where语句中含有分区字段过滤条件来限制范围,否则不允许执行。换句话说,就是用户不允许扫描所有分区。进行这个限制的原因是,通常分区表都拥有非常大
的数据集,而且数据增加迅速。没有进行分区限制的查询可能会消耗令人不可接受的巨大资源来处理这个表。
2) 对于使用了order by语句的查询,要求必须使用limit语句。因为order by为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理,强制要求用户增加这个LIMIT语
句可以防止Reducer额外执行很长一段时间。
3) 限制笛卡尔积的查询。对关系型数据库非常了解的用户可能期望在执行JOIN查询的时候不使用ON语句而是使用where语句,这样关系数据库的执行优化器就可以高效地将WHERE
语句转化成那个ON语句。不幸的是,Hive并不会执行这种优化,因此,如果表足够大,那么这个查询就会出现不可控的情况。
8. JVM重用
JVM重用是Hadoop调优参数的内容,其对Hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或task特别多的场景,这类场景大多数执行时间都很短。
Hadoop的默认配置通常是使用派生JVM来执行map和Reduce任务的。这时JVM的启动过程可能会造成相当大的开销,尤其是执行的job包含有成百上千task任务的情况。JVM重用可以
使得JVM实例在同一个job中重新使用N次。N的值可以在Hadoop的mapred-site.xml文件中进行配置。通常在10-20之间,具体多少需要根据具体业务场景测试得出。
这个功能的缺点是,开启JVM重用将一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放。如果某个“不平衡的”job中有某几个reduce task执行的时间要比其他
Reduce task消耗的时间多的多的话,那么保留的插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。
9. 推测执行
在分布式集群环境下,因为程序Bug(包括Hadoop本身的bug),负载不均衡或者资源分布不均等原因,会造成同一个作业的多个任务之间运行速度不一致,有些任务的运行速度
可能明显慢于其他任务(比如一个作业的某个任务进度只有50%,而其他所有任务已经运行完毕),则这些任务会拖慢作业的整体执行进度。为了避免这种情况发生,Hadoop采用了
推测执行(Speculative Execution)机制,它根据一定的法则推测出“拖后腿”的任务,并为这样的任务启动一个备份任务,让该任务与原始任务同时处理同一份数据,并最终选用最先
成功运行完成任务的计算结果作为最终结果。
设置开启推测执行参数:Hadoop的mapred-site.xml文件中进行配置,默认是true
关于调优这些推测执行变量,还很难给一个具体的建议。如果用户对于运行时的偏差非常敏感的话,那么可以将这些功能关闭掉。如果用户因为输入数据量很大而需要执行长时间的
map或者Reduce task的话,那么启动推测执行造成的浪费是非常巨大大。
10. 压缩
见上